@wefunder/sdk 0.1.0-beta.10 → 0.1.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +159 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +44 -1
- package/dist/index.d.ts +44 -1
- package/dist/index.js +157 -28
- package/dist/index.js.map +1 -1
- package/examples_manifest.json +2 -2
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/generated/core/bodySerializer.gen.ts","../src/generated/core/params.gen.ts","../src/generated/core/serverSentEvents.gen.ts","../src/generated/core/pathSerializer.gen.ts","../src/generated/core/utils.gen.ts","../src/generated/core/auth.gen.ts","../src/generated/client/utils.gen.ts","../src/generated/client/client.gen.ts","../src/http.ts","../src/oauth.ts","../src/errors.ts","../src/token-manager.ts","../src/pagination.ts","../src/generated/sdk.gen.ts","../src/generated/client.gen.ts","../src/client.ts","../src/webhooks.ts"],"sourcesContent":["// This file is auto-generated by @hey-api/openapi-ts\n\nimport type {\n ArrayStyle,\n ObjectStyle,\n SerializerOptions,\n} from \"./pathSerializer.gen\";\n\nexport type QuerySerializer = (query: Record<string, unknown>) => string;\n\nexport type BodySerializer = (body: unknown) => unknown;\n\ntype QuerySerializerOptionsObject = {\n allowReserved?: boolean;\n array?: Partial<SerializerOptions<ArrayStyle>>;\n object?: Partial<SerializerOptions<ObjectStyle>>;\n};\n\nexport type QuerySerializerOptions = QuerySerializerOptionsObject & {\n /**\n * Per-parameter serialization overrides. When provided, these settings\n * override the global array/object settings for specific parameter names.\n */\n parameters?: Record<string, QuerySerializerOptionsObject>;\n};\n\nconst serializeFormDataPair = (\n data: FormData,\n key: string,\n value: unknown,\n): void => {\n if (typeof value === \"string\" || value instanceof Blob) {\n data.append(key, value);\n } else if (value instanceof Date) {\n data.append(key, value.toISOString());\n } else {\n data.append(key, JSON.stringify(value));\n }\n};\n\nconst serializeUrlSearchParamsPair = (\n data: URLSearchParams,\n key: string,\n value: unknown,\n): void => {\n if (typeof value === \"string\") {\n data.append(key, value);\n } else {\n data.append(key, JSON.stringify(value));\n }\n};\n\nexport const formDataBodySerializer = {\n bodySerializer: (body: unknown): FormData => {\n const data = new FormData();\n\n Object.entries(body as Record<string, unknown>).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n if (Array.isArray(value)) {\n value.forEach((v) => serializeFormDataPair(data, key, v));\n } else {\n serializeFormDataPair(data, key, value);\n }\n });\n\n return data;\n },\n};\n\nexport const jsonBodySerializer = {\n bodySerializer: (body: unknown): string =>\n JSON.stringify(body, (_key, value) =>\n typeof value === \"bigint\" ? value.toString() : value,\n ),\n};\n\nexport const urlSearchParamsBodySerializer = {\n bodySerializer: (body: unknown): string => {\n const data = new URLSearchParams();\n\n Object.entries(body as Record<string, unknown>).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n if (Array.isArray(value)) {\n value.forEach((v) => serializeUrlSearchParamsPair(data, key, v));\n } else {\n serializeUrlSearchParamsPair(data, key, value);\n }\n });\n\n return data.toString();\n },\n};\n","// This file is auto-generated by @hey-api/openapi-ts\n\ntype Slot = \"body\" | \"headers\" | \"path\" | \"query\";\n\nexport type Field =\n | {\n in: Exclude<Slot, \"body\">;\n /**\n * Field name. This is the name we want the user to see and use.\n */\n key: string;\n /**\n * Field mapped name. This is the name we want to use in the request.\n * If omitted, we use the same value as `key`.\n */\n map?: string;\n }\n | {\n in: Extract<Slot, \"body\">;\n /**\n * Key isn't required for bodies.\n */\n key?: string;\n map?: string;\n }\n | {\n /**\n * Field name. This is the name we want the user to see and use.\n */\n key: string;\n /**\n * Field mapped name. This is the name we want to use in the request.\n * If `in` is omitted, `map` aliases `key` to the transport layer.\n */\n map: Slot;\n };\n\nexport interface Fields {\n allowExtra?: Partial<Record<Slot, boolean>>;\n args?: ReadonlyArray<Field>;\n}\n\nexport type FieldsConfig = ReadonlyArray<Field | Fields>;\n\nconst extraPrefixesMap: Record<string, Slot> = {\n $body_: \"body\",\n $headers_: \"headers\",\n $path_: \"path\",\n $query_: \"query\",\n};\nconst extraPrefixes = Object.entries(extraPrefixesMap);\n\ntype KeyMap = Map<\n string,\n | {\n in: Slot;\n map?: string;\n }\n | {\n in?: never;\n map: Slot;\n }\n>;\n\nfunction buildKeyMap(fields: FieldsConfig, map?: KeyMap): KeyMap {\n if (!map) {\n map = new Map();\n }\n\n for (const config of fields) {\n if (\"in\" in config) {\n if (config.key) {\n map.set(config.key, {\n in: config.in,\n map: config.map,\n });\n }\n } else if (\"key\" in config) {\n map.set(config.key, {\n map: config.map,\n });\n } else if (config.args) {\n buildKeyMap(config.args, map);\n }\n }\n\n return map;\n}\n\ninterface Params {\n body?: unknown;\n headers: Record<string, unknown>;\n path: Record<string, unknown>;\n query: Record<string, unknown>;\n}\n\nfunction stripEmptySlots(params: Params): void {\n for (const [slot, value] of Object.entries(params)) {\n if (slot === \"body\") continue;\n if (\n value &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n !Object.keys(value).length\n ) {\n delete params[slot as Slot];\n }\n }\n}\n\nexport function buildClientParams(\n args: ReadonlyArray<unknown>,\n fields: FieldsConfig,\n): Params {\n const params: Params = {\n headers: Object.create(null),\n path: Object.create(null),\n query: Object.create(null),\n };\n\n const map = buildKeyMap(fields);\n\n function writeSlot(slot: Slot, key: string, value: unknown): void {\n let record = params[slot] as Record<string, unknown> | undefined;\n if (record === undefined) {\n record = Object.create(null) as Record<string, unknown>;\n params[slot] = record;\n }\n record[key] = value;\n }\n\n let config: FieldsConfig[number] | undefined;\n\n for (const [index, arg] of args.entries()) {\n if (fields[index]) {\n config = fields[index];\n }\n\n if (!config) {\n continue;\n }\n\n if (\"in\" in config) {\n if (config.key) {\n const field = map.get(config.key)!;\n const name = field.map || config.key;\n if (field.in) {\n writeSlot(field.in, name, arg);\n }\n } else {\n params.body = arg;\n }\n } else {\n for (const [key, value] of Object.entries(arg ?? {})) {\n const field = map.get(key);\n\n if (field) {\n if (field.in) {\n const name = field.map || key;\n writeSlot(field.in, name, value);\n } else {\n params[field.map] = value;\n }\n } else {\n const extra = extraPrefixes.find(([prefix]) =>\n key.startsWith(prefix),\n );\n\n if (extra) {\n const [prefix, slot] = extra;\n writeSlot(slot, key.slice(prefix.length), value);\n } else if (\"allowExtra\" in config && config.allowExtra) {\n for (const [slot, allowed] of Object.entries(config.allowExtra)) {\n if (allowed) {\n writeSlot(slot as Slot, key, value);\n break;\n }\n }\n }\n }\n }\n }\n }\n\n stripEmptySlots(params);\n\n return params;\n}\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { Config } from \"./types.gen\";\n\nexport type ServerSentEventsOptions<TData = unknown> = Omit<\n RequestInit,\n \"method\"\n> &\n Pick<Config, \"method\" | \"responseTransformer\" | \"responseValidator\"> & {\n /**\n * Fetch API implementation. You can use this option to provide a custom\n * fetch instance.\n *\n * @default globalThis.fetch\n */\n fetch?: typeof fetch;\n /**\n * Implementing clients can call request interceptors inside this hook.\n */\n onRequest?: (url: string, init: RequestInit) => Promise<Request>;\n /**\n * Callback invoked when a network or parsing error occurs during streaming.\n *\n * This option applies only if the endpoint returns a stream of events.\n *\n * @param error The error that occurred.\n */\n onSseError?: (error: unknown) => void;\n /**\n * Callback invoked when an event is streamed from the server.\n *\n * This option applies only if the endpoint returns a stream of events.\n *\n * @param event Event streamed from the server.\n * @returns Nothing (void).\n */\n onSseEvent?: (event: StreamEvent<TData>) => void;\n serializedBody?: RequestInit[\"body\"];\n /**\n * Default retry delay in milliseconds.\n *\n * This option applies only if the endpoint returns a stream of events.\n *\n * @default 3000\n */\n sseDefaultRetryDelay?: number;\n /**\n * Maximum number of retry attempts before giving up.\n */\n sseMaxRetryAttempts?: number;\n /**\n * Maximum retry delay in milliseconds.\n *\n * Applies only when exponential backoff is used.\n *\n * This option applies only if the endpoint returns a stream of events.\n *\n * @default 30000\n */\n sseMaxRetryDelay?: number;\n /**\n * Optional sleep function for retry backoff.\n *\n * Defaults to using `setTimeout`.\n */\n sseSleepFn?: (ms: number) => Promise<void>;\n url: string;\n };\n\nexport interface StreamEvent<TData = unknown> {\n data: TData;\n event?: string;\n id?: string;\n retry?: number;\n}\n\nexport type ServerSentEventsResult<\n TData = unknown,\n TReturn = void,\n TNext = unknown,\n> = {\n stream: AsyncGenerator<\n TData extends Record<string, unknown> ? TData[keyof TData] : TData,\n TReturn,\n TNext\n >;\n};\n\nexport function createSseClient<TData = unknown>({\n onRequest,\n onSseError,\n onSseEvent,\n responseTransformer,\n responseValidator,\n sseDefaultRetryDelay,\n sseMaxRetryAttempts,\n sseMaxRetryDelay,\n sseSleepFn,\n url,\n ...options\n}: ServerSentEventsOptions): ServerSentEventsResult<TData> {\n let lastEventId: string | undefined;\n\n const sleep =\n sseSleepFn ??\n ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms)));\n\n const createStream = async function* () {\n let retryDelay: number = sseDefaultRetryDelay ?? 3000;\n let attempt = 0;\n const signal = options.signal ?? new AbortController().signal;\n\n while (true) {\n if (signal.aborted) break;\n\n attempt++;\n\n const headers =\n options.headers instanceof Headers\n ? options.headers\n : new Headers(options.headers as Record<string, string> | undefined);\n\n if (lastEventId !== undefined) {\n headers.set(\"Last-Event-ID\", lastEventId);\n }\n\n try {\n const requestInit: RequestInit = {\n redirect: \"follow\",\n ...options,\n body: options.serializedBody,\n headers,\n signal,\n };\n let request = new Request(url, requestInit);\n if (onRequest) {\n request = await onRequest(url, requestInit);\n }\n // fetch must be assigned here, otherwise it would throw the error:\n // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation\n const _fetch = options.fetch ?? globalThis.fetch;\n const response = await _fetch(request);\n\n if (!response.ok)\n throw new Error(\n `SSE failed: ${response.status} ${response.statusText}`,\n );\n\n if (!response.body) throw new Error(\"No body in SSE response\");\n\n const reader = response.body\n .pipeThrough(new TextDecoderStream())\n .getReader();\n\n let buffer = \"\";\n\n const abortHandler = () => {\n try {\n reader.cancel();\n } catch {\n // noop\n }\n };\n\n signal.addEventListener(\"abort\", abortHandler);\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += value;\n buffer = buffer.replace(/\\r\\n?/g, \"\\n\"); // normalize line endings\n\n const chunks = buffer.split(\"\\n\\n\");\n buffer = chunks.pop() ?? \"\";\n\n for (const chunk of chunks) {\n const lines = chunk.split(\"\\n\");\n const dataLines: Array<string> = [];\n let eventName: string | undefined;\n\n for (const line of lines) {\n if (line.startsWith(\"data:\")) {\n dataLines.push(line.replace(/^data:\\s*/, \"\"));\n } else if (line.startsWith(\"event:\")) {\n eventName = line.replace(/^event:\\s*/, \"\");\n } else if (line.startsWith(\"id:\")) {\n lastEventId = line.replace(/^id:\\s*/, \"\");\n } else if (line.startsWith(\"retry:\")) {\n const parsed = Number.parseInt(\n line.replace(/^retry:\\s*/, \"\"),\n 10,\n );\n if (!Number.isNaN(parsed)) {\n retryDelay = parsed;\n }\n }\n }\n\n let data: unknown;\n let parsedJson = false;\n\n if (dataLines.length) {\n const rawData = dataLines.join(\"\\n\");\n try {\n data = JSON.parse(rawData);\n parsedJson = true;\n } catch {\n data = rawData;\n }\n }\n\n if (parsedJson) {\n if (responseValidator) {\n await responseValidator(data);\n }\n\n if (responseTransformer) {\n data = await responseTransformer(data);\n }\n }\n\n onSseEvent?.({\n data,\n event: eventName,\n id: lastEventId,\n retry: retryDelay,\n });\n\n if (dataLines.length) {\n yield data as any;\n }\n }\n }\n } finally {\n signal.removeEventListener(\"abort\", abortHandler);\n reader.releaseLock();\n }\n\n break; // exit loop on normal completion\n } catch (error) {\n // connection failed or aborted; retry after delay\n onSseError?.(error);\n\n if (\n sseMaxRetryAttempts !== undefined &&\n attempt >= sseMaxRetryAttempts\n ) {\n break; // stop after firing error\n }\n\n // exponential backoff: double retry each attempt, cap at 30s\n const backoff = Math.min(\n retryDelay * 2 ** (attempt - 1),\n sseMaxRetryDelay ?? 30000,\n );\n await sleep(backoff);\n }\n }\n };\n\n const stream = createStream();\n\n return { stream };\n}\n","// This file is auto-generated by @hey-api/openapi-ts\n\ninterface SerializeOptions<T>\n extends SerializePrimitiveOptions, SerializerOptions<T> {}\n\ninterface SerializePrimitiveOptions {\n allowReserved?: boolean;\n name: string;\n}\n\nexport interface SerializerOptions<T> {\n /**\n * @default true\n */\n explode: boolean;\n style: T;\n}\n\nexport type ArrayStyle = \"form\" | \"spaceDelimited\" | \"pipeDelimited\";\nexport type ArraySeparatorStyle = ArrayStyle | MatrixStyle;\ntype MatrixStyle = \"label\" | \"matrix\" | \"simple\";\nexport type ObjectStyle = \"form\" | \"deepObject\";\ntype ObjectSeparatorStyle = ObjectStyle | MatrixStyle;\n\ninterface SerializePrimitiveParam extends SerializePrimitiveOptions {\n value: string;\n}\n\nexport const separatorArrayExplode = (\n style: ArraySeparatorStyle,\n): \".\" | \";\" | \",\" | \"&\" => {\n switch (style) {\n case \"label\":\n return \".\";\n case \"matrix\":\n return \";\";\n case \"simple\":\n return \",\";\n default:\n return \"&\";\n }\n};\n\nexport const separatorArrayNoExplode = (\n style: ArraySeparatorStyle,\n): \",\" | \"|\" | \"%20\" => {\n switch (style) {\n case \"form\":\n return \",\";\n case \"pipeDelimited\":\n return \"|\";\n case \"spaceDelimited\":\n return \"%20\";\n default:\n return \",\";\n }\n};\n\nexport const separatorObjectExplode = (\n style: ObjectSeparatorStyle,\n): \".\" | \";\" | \",\" | \"&\" => {\n switch (style) {\n case \"label\":\n return \".\";\n case \"matrix\":\n return \";\";\n case \"simple\":\n return \",\";\n default:\n return \"&\";\n }\n};\n\nexport const serializeArrayParam = ({\n allowReserved,\n explode,\n name,\n style,\n value,\n}: SerializeOptions<ArraySeparatorStyle> & {\n value: unknown[];\n}): string => {\n if (!explode) {\n const joinedValues = (\n allowReserved ? value : value.map((v) => encodeURIComponent(v as string))\n ).join(separatorArrayNoExplode(style));\n switch (style) {\n case \"label\":\n return `.${joinedValues}`;\n case \"matrix\":\n return `;${name}=${joinedValues}`;\n case \"simple\":\n return joinedValues;\n default:\n return `${name}=${joinedValues}`;\n }\n }\n\n const separator = separatorArrayExplode(style);\n const joinedValues = value\n .map((v) => {\n if (style === \"label\" || style === \"simple\") {\n return allowReserved ? v : encodeURIComponent(v as string);\n }\n\n return serializePrimitiveParam({\n allowReserved,\n name,\n value: v as string,\n });\n })\n .join(separator);\n return style === \"label\" || style === \"matrix\"\n ? separator + joinedValues\n : joinedValues;\n};\n\nexport const serializePrimitiveParam = ({\n allowReserved,\n name,\n value,\n}: SerializePrimitiveParam): string => {\n if (value === undefined || value === null) {\n return \"\";\n }\n\n if (typeof value === \"object\") {\n throw new Error(\n \"Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.\",\n );\n }\n\n return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;\n};\n\nexport const serializeObjectParam = ({\n allowReserved,\n explode,\n name,\n style,\n value,\n valueOnly,\n}: SerializeOptions<ObjectSeparatorStyle> & {\n value: Record<string, unknown> | Date;\n valueOnly?: boolean;\n}): string => {\n if (value instanceof Date) {\n return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;\n }\n\n if (style !== \"deepObject\" && !explode) {\n let values: string[] = [];\n Object.entries(value).forEach(([key, v]) => {\n values = [\n ...values,\n key,\n allowReserved ? (v as string) : encodeURIComponent(v as string),\n ];\n });\n const joinedValues = values.join(\",\");\n switch (style) {\n case \"form\":\n return `${name}=${joinedValues}`;\n case \"label\":\n return `.${joinedValues}`;\n case \"matrix\":\n return `;${name}=${joinedValues}`;\n default:\n return joinedValues;\n }\n }\n\n const separator = separatorObjectExplode(style);\n const joinedValues = Object.entries(value)\n .map(([key, v]) =>\n serializePrimitiveParam({\n allowReserved,\n name: style === \"deepObject\" ? `${name}[${key}]` : key,\n value: v as string,\n }),\n )\n .join(separator);\n return style === \"label\" || style === \"matrix\"\n ? separator + joinedValues\n : joinedValues;\n};\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { BodySerializer, QuerySerializer } from \"./bodySerializer.gen\";\nimport {\n type ArraySeparatorStyle,\n serializeArrayParam,\n serializeObjectParam,\n serializePrimitiveParam,\n} from \"./pathSerializer.gen\";\n\nexport interface PathSerializer {\n path: Record<string, unknown>;\n url: string;\n}\n\nexport const PATH_PARAM_RE: RegExp = /\\{[^{}]+\\}/g;\n\nexport const defaultPathSerializer = ({\n path,\n url: _url,\n}: PathSerializer): string => {\n let url = _url;\n const matches = _url.match(PATH_PARAM_RE);\n if (matches) {\n for (const match of matches) {\n let explode = false;\n let name = match.substring(1, match.length - 1);\n let style: ArraySeparatorStyle = \"simple\";\n\n if (name.endsWith(\"*\")) {\n explode = true;\n name = name.substring(0, name.length - 1);\n }\n\n if (name.startsWith(\".\")) {\n name = name.substring(1);\n style = \"label\";\n } else if (name.startsWith(\";\")) {\n name = name.substring(1);\n style = \"matrix\";\n }\n\n const value = path[name];\n\n if (value === undefined || value === null) {\n continue;\n }\n\n if (Array.isArray(value)) {\n url = url.replace(\n match,\n serializeArrayParam({ explode, name, style, value }),\n );\n continue;\n }\n\n if (typeof value === \"object\") {\n url = url.replace(\n match,\n serializeObjectParam({\n explode,\n name,\n style,\n value: value as Record<string, unknown>,\n valueOnly: true,\n }),\n );\n continue;\n }\n\n if (style === \"matrix\") {\n url = url.replace(\n match,\n `;${serializePrimitiveParam({\n name,\n value: value as string,\n })}`,\n );\n continue;\n }\n\n const replaceValue = encodeURIComponent(\n style === \"label\" ? `.${value as string}` : (value as string),\n );\n url = url.replace(match, replaceValue);\n }\n }\n return url;\n};\n\nexport const getUrl = ({\n baseUrl,\n path,\n query,\n querySerializer,\n url: _url,\n}: {\n baseUrl?: string;\n path?: Record<string, unknown>;\n query?: Record<string, unknown>;\n querySerializer: QuerySerializer;\n url: string;\n}): string => {\n const pathUrl = _url.startsWith(\"/\") ? _url : `/${_url}`;\n let url = (baseUrl ?? \"\") + pathUrl;\n if (path) {\n url = defaultPathSerializer({ path, url });\n }\n let search = query ? querySerializer(query) : \"\";\n if (search.startsWith(\"?\")) {\n search = search.substring(1);\n }\n if (search) {\n url += `?${search}`;\n }\n return url;\n};\n\nexport function getValidRequestBody(options: {\n body?: unknown;\n bodySerializer?: BodySerializer | null;\n serializedBody?: unknown;\n}): unknown {\n const hasBody = options.body !== undefined;\n const isSerializedBody = hasBody && options.bodySerializer;\n\n if (isSerializedBody) {\n if (\"serializedBody\" in options) {\n const hasSerializedBody =\n options.serializedBody !== undefined && options.serializedBody !== \"\";\n\n return hasSerializedBody ? options.serializedBody : null;\n }\n\n // not all clients implement a serializedBody property (i.e., client-axios)\n return options.body !== \"\" ? options.body : null;\n }\n\n // plain/text body\n if (hasBody) {\n return options.body;\n }\n\n // no body was provided\n return undefined;\n}\n","// This file is auto-generated by @hey-api/openapi-ts\n\nexport type AuthToken = string | undefined;\n\nexport interface Auth {\n /**\n * Which part of the request do we use to send the auth?\n *\n * @default 'header'\n */\n in?: \"header\" | \"query\" | \"cookie\";\n /**\n * A unique identifier for the security scheme.\n *\n * Defined only when there are multiple security schemes whose `Auth`\n * shape would otherwise be identical.\n */\n key?: string;\n /**\n * Header or query parameter name.\n *\n * @default 'Authorization'\n */\n name?: string;\n scheme?: \"basic\" | \"bearer\";\n type: \"apiKey\" | \"http\";\n}\n\nexport const getAuthToken = async (\n auth: Auth,\n callback: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken,\n): Promise<string | undefined> => {\n const token =\n typeof callback === \"function\" ? await callback(auth) : callback;\n\n if (!token) {\n return;\n }\n\n if (auth.scheme === \"bearer\") {\n return `Bearer ${token}`;\n }\n\n if (auth.scheme === \"basic\") {\n return `Basic ${btoa(token)}`;\n }\n\n return token;\n};\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport { getAuthToken } from \"../core/auth.gen\";\nimport type { QuerySerializerOptions } from \"../core/bodySerializer.gen\";\nimport { jsonBodySerializer } from \"../core/bodySerializer.gen\";\nimport {\n serializeArrayParam,\n serializeObjectParam,\n serializePrimitiveParam,\n} from \"../core/pathSerializer.gen\";\nimport { getUrl } from \"../core/utils.gen\";\nimport type {\n Client,\n ClientOptions,\n Config,\n RequestOptions,\n} from \"./types.gen\";\n\nexport const createQuerySerializer = <T = unknown>({\n parameters = {},\n ...args\n}: QuerySerializerOptions = {}): ((queryParams: T) => string) => {\n const querySerializer = (queryParams: T): string => {\n const search: string[] = [];\n if (queryParams && typeof queryParams === \"object\") {\n for (const name in queryParams) {\n const value = queryParams[name];\n\n if (value === undefined || value === null) {\n continue;\n }\n\n const options = parameters[name] || args;\n\n if (Array.isArray(value)) {\n const serializedArray = serializeArrayParam({\n allowReserved: options.allowReserved,\n explode: true,\n name,\n style: \"form\",\n value,\n ...options.array,\n });\n if (serializedArray) search.push(serializedArray);\n } else if (typeof value === \"object\") {\n const serializedObject = serializeObjectParam({\n allowReserved: options.allowReserved,\n explode: true,\n name,\n style: \"deepObject\",\n value: value as Record<string, unknown>,\n ...options.object,\n });\n if (serializedObject) search.push(serializedObject);\n } else {\n const serializedPrimitive = serializePrimitiveParam({\n allowReserved: options.allowReserved,\n name,\n value: value as string,\n });\n if (serializedPrimitive) search.push(serializedPrimitive);\n }\n }\n }\n return search.join(\"&\");\n };\n return querySerializer;\n};\n\n/**\n * Infers parseAs value from provided Content-Type header.\n */\nexport const getParseAs = (\n contentType: string | null,\n): Exclude<Config[\"parseAs\"], \"auto\"> => {\n if (!contentType) {\n // If no Content-Type header is provided, the best we can do is return the raw response body,\n // which is effectively the same as the 'stream' option.\n return \"stream\";\n }\n\n const cleanContent = contentType.split(\";\")[0]?.trim();\n\n if (!cleanContent) {\n return;\n }\n\n if (\n cleanContent.startsWith(\"application/json\") ||\n cleanContent.endsWith(\"+json\")\n ) {\n return \"json\";\n }\n\n if (cleanContent === \"multipart/form-data\") {\n return \"formData\";\n }\n\n if (\n [\"application/\", \"audio/\", \"image/\", \"video/\"].some((type) =>\n cleanContent.startsWith(type),\n )\n ) {\n return \"blob\";\n }\n\n if (cleanContent.startsWith(\"text/\")) {\n return \"text\";\n }\n\n return;\n};\n\nconst checkForExistence = (\n options: Pick<RequestOptions, \"auth\" | \"query\"> & {\n headers: Headers;\n },\n name?: string,\n): boolean => {\n if (!name) {\n return false;\n }\n if (\n options.headers.has(name) ||\n options.query?.[name] ||\n options.headers.get(\"Cookie\")?.includes(`${name}=`)\n ) {\n return true;\n }\n return false;\n};\n\nexport async function setAuthParams(\n options: Pick<RequestOptions, \"auth\" | \"query\" | \"security\"> & {\n headers: Headers;\n },\n): Promise<void> {\n for (const auth of options.security ?? []) {\n if (checkForExistence(options, auth.name)) {\n continue;\n }\n\n const token = await getAuthToken(auth, options.auth);\n\n if (!token) {\n continue;\n }\n\n const name = auth.name ?? \"Authorization\";\n\n switch (auth.in) {\n case \"query\":\n if (!options.query) {\n options.query = {};\n }\n options.query[name] = token;\n break;\n case \"cookie\":\n options.headers.append(\"Cookie\", `${name}=${token}`);\n break;\n case \"header\":\n default:\n options.headers.set(name, token);\n break;\n }\n }\n}\n\nexport const buildUrl: Client[\"buildUrl\"] = (options) =>\n getUrl({\n baseUrl: options.baseUrl as string,\n path: options.path,\n query: options.query,\n querySerializer:\n typeof options.querySerializer === \"function\"\n ? options.querySerializer\n : createQuerySerializer(options.querySerializer),\n url: options.url,\n });\n\nexport const mergeConfigs = (a: Config, b: Config): Config => {\n const config = { ...a, ...b };\n if (config.baseUrl?.endsWith(\"/\")) {\n config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);\n }\n config.headers = mergeHeaders(a.headers, b.headers);\n return config;\n};\n\nconst headersEntries = (headers: Headers): Array<[string, string]> => {\n const entries: Array<[string, string]> = [];\n headers.forEach((value, key) => {\n entries.push([key, value]);\n });\n return entries;\n};\n\nexport const mergeHeaders = (\n ...headers: Array<Required<Config>[\"headers\"] | undefined>\n): Headers => {\n const mergedHeaders = new Headers();\n for (const header of headers) {\n if (!header) {\n continue;\n }\n\n const iterator =\n header instanceof Headers\n ? headersEntries(header)\n : Object.entries(header);\n\n for (const [key, value] of iterator) {\n if (value === null) {\n mergedHeaders.delete(key);\n } else if (Array.isArray(value)) {\n for (const v of value) {\n mergedHeaders.append(key, v as string);\n }\n } else if (value !== undefined) {\n // assume object headers are meant to be JSON stringified, i.e., their\n // content value in OpenAPI specification is 'application/json'\n mergedHeaders.set(\n key,\n typeof value === \"object\" ? JSON.stringify(value) : (value as string),\n );\n }\n }\n }\n return mergedHeaders;\n};\n\ntype ErrInterceptor<Err, Res, Req, Options> = (\n error: Err,\n /** response may be undefined due to a network error where no response object is produced */\n response: Res | undefined,\n /** request may be undefined, because error may be from building the request object itself */\n request: Req | undefined,\n options: Options,\n) => Err | Promise<Err>;\n\ntype ReqInterceptor<Req, Options> = (\n request: Req,\n options: Options,\n) => Req | Promise<Req>;\n\ntype ResInterceptor<Res, Req, Options> = (\n response: Res,\n request: Req,\n options: Options,\n) => Res | Promise<Res>;\n\nclass Interceptors<Interceptor> {\n fns: Array<Interceptor | null> = [];\n\n clear(): void {\n this.fns = [];\n }\n\n eject(id: number | Interceptor): void {\n const index = this.getInterceptorIndex(id);\n if (this.fns[index]) {\n this.fns[index] = null;\n }\n }\n\n exists(id: number | Interceptor): boolean {\n const index = this.getInterceptorIndex(id);\n return Boolean(this.fns[index]);\n }\n\n getInterceptorIndex(id: number | Interceptor): number {\n if (typeof id === \"number\") {\n return this.fns[id] ? id : -1;\n }\n return this.fns.indexOf(id);\n }\n\n update(\n id: number | Interceptor,\n fn: Interceptor,\n ): number | Interceptor | false {\n const index = this.getInterceptorIndex(id);\n if (this.fns[index]) {\n this.fns[index] = fn;\n return id;\n }\n return false;\n }\n\n use(fn: Interceptor): number {\n this.fns.push(fn);\n return this.fns.length - 1;\n }\n}\n\nexport interface Middleware<Req, Res, Err, Options> {\n error: Interceptors<ErrInterceptor<Err, Res, Req, Options>>;\n request: Interceptors<ReqInterceptor<Req, Options>>;\n response: Interceptors<ResInterceptor<Res, Req, Options>>;\n}\n\nexport const createInterceptors = <Req, Res, Err, Options>(): Middleware<\n Req,\n Res,\n Err,\n Options\n> => ({\n error: new Interceptors<ErrInterceptor<Err, Res, Req, Options>>(),\n request: new Interceptors<ReqInterceptor<Req, Options>>(),\n response: new Interceptors<ResInterceptor<Res, Req, Options>>(),\n});\n\nconst defaultQuerySerializer = createQuerySerializer({\n allowReserved: false,\n array: {\n explode: true,\n style: \"form\",\n },\n object: {\n explode: true,\n style: \"deepObject\",\n },\n});\n\nconst defaultHeaders = {\n \"Content-Type\": \"application/json\",\n};\n\nexport const createConfig = <T extends ClientOptions = ClientOptions>(\n override: Config<Omit<ClientOptions, keyof T> & T> = {},\n): Config<Omit<ClientOptions, keyof T> & T> => ({\n ...jsonBodySerializer,\n headers: defaultHeaders,\n parseAs: \"auto\",\n querySerializer: defaultQuerySerializer,\n ...override,\n});\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport { createSseClient } from \"../core/serverSentEvents.gen\";\nimport type { HttpMethod } from \"../core/types.gen\";\nimport { getValidRequestBody } from \"../core/utils.gen\";\nimport type {\n Client,\n Config,\n RequestOptions,\n ResolvedRequestOptions,\n} from \"./types.gen\";\nimport {\n buildUrl,\n createConfig,\n createInterceptors,\n getParseAs,\n mergeConfigs,\n mergeHeaders,\n setAuthParams,\n} from \"./utils.gen\";\n\ntype ReqInit = Omit<RequestInit, \"body\" | \"headers\"> & {\n body?: any;\n headers: ReturnType<typeof mergeHeaders>;\n};\n\nexport const createClient = (config: Config = {}): Client => {\n let _config = mergeConfigs(createConfig(), config);\n\n const getConfig = (): Config => ({ ..._config });\n\n const setConfig = (config: Config): Config => {\n _config = mergeConfigs(_config, config);\n return getConfig();\n };\n\n const interceptors = createInterceptors<\n Request,\n Response,\n unknown,\n ResolvedRequestOptions\n >();\n\n const beforeRequest = async <\n TData = unknown,\n TResponseStyle extends \"data\" | \"fields\" = \"fields\",\n ThrowOnError extends boolean = boolean,\n Url extends string = string,\n >(\n options: RequestOptions<TData, TResponseStyle, ThrowOnError, Url>,\n ) => {\n const opts = {\n ..._config,\n ...options,\n fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,\n headers: mergeHeaders(_config.headers, options.headers),\n serializedBody: undefined as string | undefined,\n };\n\n if (opts.security) {\n await setAuthParams(opts);\n }\n\n if (opts.requestValidator) {\n await opts.requestValidator(opts);\n }\n\n if (opts.body !== undefined && opts.bodySerializer) {\n opts.serializedBody = opts.bodySerializer(opts.body) as\n string | undefined;\n }\n\n // remove Content-Type header if body is empty to avoid sending invalid requests\n if (opts.body === undefined || opts.serializedBody === \"\") {\n opts.headers.delete(\"Content-Type\");\n }\n\n const resolvedOpts = opts as typeof opts &\n ResolvedRequestOptions<TResponseStyle, ThrowOnError, Url>;\n const url = buildUrl(resolvedOpts);\n\n return { opts: resolvedOpts, url };\n };\n\n const request: Client[\"request\"] = async (options) => {\n const throwOnError = options.throwOnError ?? _config.throwOnError;\n const responseStyle = options.responseStyle ?? _config.responseStyle;\n\n let request: Request | undefined;\n let response: Response | undefined;\n\n try {\n const { opts, url } = await beforeRequest(options);\n const requestInit: ReqInit = {\n redirect: \"follow\",\n ...opts,\n body: getValidRequestBody(opts),\n };\n\n request = new Request(url, requestInit);\n\n for (const fn of interceptors.request.fns) {\n if (fn) {\n request = await fn(request, opts);\n }\n }\n\n // fetch must be assigned here, otherwise it would throw the error:\n // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation\n const _fetch = opts.fetch!;\n\n response = await _fetch(request);\n\n for (const fn of interceptors.response.fns) {\n if (fn) {\n response = await fn(response, request, opts);\n }\n }\n\n const result = {\n request,\n response,\n };\n\n if (response.ok) {\n const parseAs =\n (opts.parseAs === \"auto\"\n ? getParseAs(response.headers.get(\"Content-Type\"))\n : opts.parseAs) ?? \"json\";\n\n if (\n response.status === 204 ||\n response.headers.get(\"Content-Length\") === \"0\"\n ) {\n let emptyData: any;\n switch (parseAs) {\n case \"arrayBuffer\":\n case \"blob\":\n case \"text\":\n emptyData = await response[parseAs]();\n break;\n case \"formData\":\n emptyData = new FormData();\n break;\n case \"stream\":\n emptyData = response.body;\n break;\n case \"json\":\n default:\n emptyData = {};\n break;\n }\n return opts.responseStyle === \"data\"\n ? emptyData\n : {\n data: emptyData,\n ...result,\n };\n }\n\n let data: any;\n switch (parseAs) {\n case \"arrayBuffer\":\n case \"blob\":\n case \"formData\":\n case \"text\":\n data = await response[parseAs]();\n break;\n case \"json\": {\n // Some servers return 200 with no Content-Length and empty body.\n // response.json() would throw; read as text and parse if non-empty.\n const text = await response.text();\n data = text ? JSON.parse(text) : {};\n break;\n }\n case \"stream\":\n return opts.responseStyle === \"data\"\n ? response.body\n : {\n data: response.body,\n ...result,\n };\n }\n\n if (parseAs === \"json\") {\n if (opts.responseValidator) {\n await opts.responseValidator(data);\n }\n\n if (opts.responseTransformer) {\n data = await opts.responseTransformer(data);\n }\n }\n\n return opts.responseStyle === \"data\"\n ? data\n : {\n data,\n ...result,\n };\n }\n\n const textError = await response.text();\n let jsonError: unknown;\n\n try {\n jsonError = JSON.parse(textError);\n } catch {\n // noop\n }\n\n throw jsonError ?? textError;\n } catch (error) {\n let finalError = error;\n\n for (const fn of interceptors.error.fns) {\n if (fn) {\n finalError = await fn(\n finalError,\n response,\n request,\n options as ResolvedRequestOptions,\n );\n }\n }\n\n finalError = finalError || {};\n\n if (throwOnError) {\n throw finalError;\n }\n\n // TODO: we probably want to return error and improve types\n return responseStyle === \"data\"\n ? undefined\n : {\n error: finalError,\n request,\n response,\n };\n }\n };\n\n const makeMethodFn =\n (method: Uppercase<HttpMethod>) => (options: RequestOptions) =>\n request({ ...options, method });\n\n const makeSseFn =\n (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {\n const { opts, url } = await beforeRequest(options);\n return createSseClient({\n ...opts,\n body: opts.body as BodyInit | null | undefined,\n method,\n onRequest: async (url, init) => {\n let request = new Request(url, init);\n for (const fn of interceptors.request.fns) {\n if (fn) {\n request = await fn(request, opts);\n }\n }\n return request;\n },\n serializedBody: getValidRequestBody(opts) as\n BodyInit | null | undefined,\n url,\n });\n };\n\n const _buildUrl: Client[\"buildUrl\"] = (options) =>\n buildUrl({ ..._config, ...options });\n\n return {\n buildUrl: _buildUrl,\n connect: makeMethodFn(\"CONNECT\"),\n delete: makeMethodFn(\"DELETE\"),\n get: makeMethodFn(\"GET\"),\n getConfig,\n head: makeMethodFn(\"HEAD\"),\n interceptors,\n options: makeMethodFn(\"OPTIONS\"),\n patch: makeMethodFn(\"PATCH\"),\n post: makeMethodFn(\"POST\"),\n put: makeMethodFn(\"PUT\"),\n request,\n setConfig,\n sse: {\n connect: makeSseFn(\"CONNECT\"),\n delete: makeSseFn(\"DELETE\"),\n get: makeSseFn(\"GET\"),\n head: makeSseFn(\"HEAD\"),\n options: makeSseFn(\"OPTIONS\"),\n patch: makeSseFn(\"PATCH\"),\n post: makeSseFn(\"POST\"),\n put: makeSseFn(\"PUT\"),\n trace: makeSseFn(\"TRACE\"),\n },\n trace: makeMethodFn(\"TRACE\"),\n } as Client;\n};\n","// The retry/refresh fetch wrapper passed to the generated client. Centralizes the\n// three contract-driven behaviors (plan §4.1 #6, §9):\n// - 401 -> refresh the token (rotation, via TokenManager) and retry ONCE\n// - 429 -> honor X-RateLimit-Reset (NOT Retry-After) and retry (safe: request was\n// rejected, not processed)\n// - 5xx / network error -> retry IDEMPOTENT requests only (GET/HEAD) with\n// exponential backoff + jitter. Writes are never auto-retried (no\n// universal idempotency key).\n\nimport type { TokenManager } from \"./token-manager.js\";\n\nexport interface RetryOptions {\n maxRetries?: number;\n baseDelayMs?: number;\n maxDelayMs?: number;\n}\n\nexport interface HttpDeps {\n tokenManager?: TokenManager;\n fetch?: typeof fetch;\n sleep?: (ms: number) => Promise<void>;\n now?: () => number;\n /** Deterministic jitter source for tests; defaults to Math.random. */\n random?: () => number;\n retry?: RetryOptions;\n}\n\ntype FetchInput = Parameters<typeof fetch>[0];\n\nconst IDEMPOTENT = new Set([\"GET\", \"HEAD\", \"OPTIONS\"]);\n\nfunction methodOf(input: FetchInput, init?: RequestInit): string {\n if (init?.method) return init.method.toUpperCase();\n if (input instanceof Request) return input.method.toUpperCase();\n return \"GET\";\n}\n\n/**\n * Compute how long to wait for a 429, reading X-RateLimit-Reset. The header may be\n * either an absolute epoch-seconds timestamp or a delta in seconds — handle both.\n * Bounded so a misbehaving header can't hang the caller.\n */\nexport function rateLimitWaitMs(response: Response, now: number, maxDelayMs: number): number {\n const raw = response.headers.get(\"x-ratelimit-reset\");\n if (!raw) return Math.min(1000, maxDelayMs);\n const n = Number(raw);\n if (!Number.isFinite(n)) return Math.min(1000, maxDelayMs);\n // Heuristic: values larger than ~now-in-seconds are absolute epoch timestamps.\n const wait = n > 1_000_000_000 ? n * 1000 - now : n * 1000;\n return Math.max(0, Math.min(wait, maxDelayMs));\n}\n\nfunction backoffMs(attempt: number, opts: Required<RetryOptions>, random: () => number): number {\n const exp = opts.baseDelayMs * 2 ** attempt;\n const jitter = exp * 0.5 * random();\n return Math.min(exp + jitter, opts.maxDelayMs);\n}\n\nexport function createFetch(deps: HttpDeps): typeof fetch {\n const baseFetch = deps.fetch ?? fetch;\n const sleep = deps.sleep ?? ((ms: number) => new Promise<void>((r) => setTimeout(r, ms)));\n const now = deps.now ?? Date.now;\n const random = deps.random ?? Math.random;\n const retry: Required<RetryOptions> = {\n maxRetries: deps.retry?.maxRetries ?? 2,\n baseDelayMs: deps.retry?.baseDelayMs ?? 250,\n maxDelayMs: deps.retry?.maxDelayMs ?? 60_000,\n };\n\n return async function wrappedFetch(input: FetchInput, init?: RequestInit): Promise<Response> {\n const method = methodOf(input, init);\n const idempotent = IDEMPOTENT.has(method);\n const isRequest = input instanceof Request;\n let refreshed = false;\n let attempt = 0;\n let retryToken: string | undefined; // set after a refresh, applied to the next attempt\n\n // Issue the request for one attempt. CRITICAL: a `Request` body is a single-use\n // stream — the hey-api client hands us a `Request`, and the first fetch consumes\n // it, so we must NOT re-dispatch the same object on a retry. Clone per attempt\n // (leaving `input` pristine), overriding the bearer after a refresh. For the\n // (url, init) form, a string body is freely re-sendable.\n const dispatch = (authToken?: string): Promise<Response> => {\n if (isRequest) {\n const fresh = (input as Request).clone();\n if (authToken === undefined) return baseFetch(fresh);\n const headers = new Headers(fresh.headers);\n headers.set(\"Authorization\", `Bearer ${authToken}`);\n return baseFetch(new Request(fresh, { headers }));\n }\n const nextInit =\n authToken === undefined\n ? init\n : (() => {\n const headers = new Headers(init?.headers);\n headers.set(\"Authorization\", `Bearer ${authToken}`);\n return { ...init, headers };\n })();\n return baseFetch(input, nextInit);\n };\n\n for (;;) {\n let response: Response | undefined;\n let networkError: unknown;\n try {\n response = await dispatch(retryToken);\n } catch (err) {\n networkError = err;\n }\n\n // --- 401: refresh once, then retry (any method — a 401 means the request was\n // rejected before processing, so re-sending is safe; the per-attempt clone makes\n // body-bearing writes replayable). ---\n if (response?.status === 401 && !refreshed && deps.tokenManager?.canRefresh) {\n refreshed = true;\n const next = await deps.tokenManager.refresh();\n retryToken = next.accessToken;\n continue;\n }\n\n // --- 429: honor X-RateLimit-Reset, retry (bounded) ---\n if (response?.status === 429 && attempt < retry.maxRetries) {\n attempt++;\n await sleep(rateLimitWaitMs(response, now(), retry.maxDelayMs));\n continue;\n }\n\n // --- 5xx / network: retry idempotent only ---\n const transient = networkError !== undefined || (response !== undefined && response.status >= 500);\n if (transient && idempotent && attempt < retry.maxRetries) {\n attempt++;\n await sleep(backoffMs(attempt, retry, random));\n continue;\n }\n\n if (response) return response;\n throw networkError;\n }\n };\n}\n","// OAuth 2.0 helpers. The contract review established:\n// - BOTH authorization_code + PKCE (user flows) AND client_credentials (server, read:public)\n// - refresh tokens ROTATE: every refresh returns a NEW refresh token that MUST be persisted\n//\n// HOST SPLIT: /authorize and /token live on different hosts by purpose.\n// - /token (+ refresh) is on api.wefunder.com — the edge gateway routes by the\n// credential's mode segment (form-body client_id for /oauth/token), so a pk_test_\n// grant mints in the sandbox cluster and a pk_live_ grant in live. ONE token host\n// for both modes; do NOT route by prefix here. (wefunder.com/oauth/token still works\n// as a transition alias but mints into live — wrong for sandbox once the gateway is\n// in front of the API, so we default to the gateway host.)\n// - /authorize is the browser consent redirect (needs the human session). Live consent\n// is on wefunder.com; sandbox (pk_test_) consent is on the canonical sandbox host\n// oauth.wefunder-sandbox.com. createAuthorizationUrl picks by client_id prefix.\n// All hosts remain independently overridable (authorizeBaseUrl / tokenBaseUrl).\n//\n// These helpers are framework-agnostic and depend only on Web Crypto + fetch (Node 18+).\n\nimport { createHash, randomBytes } from \"node:crypto\";\n\n/** Host for the LIVE browser /authorize redirect (pk_live_ / default). */\nexport const DEFAULT_AUTHORIZE_BASE_URL = \"https://wefunder.com/oauth\";\n\n/** Host for the SANDBOX browser /authorize redirect (pk_test_). Canonical, client_id-derivable. */\nexport const SANDBOX_AUTHORIZE_BASE_URL = \"https://oauth.wefunder-sandbox.com/oauth\";\n\n// Host for /token (+ refresh). The edge gateway routes test/live by the client_id mode,\n// so one host serves both. Callers can override via `tokenBaseUrl`.\nexport const DEFAULT_TOKEN_BASE_URL = \"https://api.wefunder.com/oauth\";\n\n/**\n * @deprecated Use `authorizeBaseUrl` / `tokenBaseUrl` instead. Kept as a convenience\n * alias that sets BOTH hosts at once. Equals the authorize default today.\n */\nexport const DEFAULT_OAUTH_BASE_URL = DEFAULT_AUTHORIZE_BASE_URL;\n\n/** Hosts can be set together (`oauthBaseUrl`) or independently. Precedence: specific > alias > default. */\nexport interface OAuthHostOptions {\n /** Overrides BOTH hosts. Prefer the specific options below. */\n oauthBaseUrl?: string;\n /** Host for the /authorize redirect. */\n authorizeBaseUrl?: string;\n /** Host for /token + refresh. */\n tokenBaseUrl?: string;\n}\n\n/** The default authorize host for a client_id: sandbox host for pk_test_, else live. */\nfunction defaultAuthorizeBase(clientId: string): string {\n return clientId.startsWith(\"pk_test_\") ? SANDBOX_AUTHORIZE_BASE_URL : DEFAULT_AUTHORIZE_BASE_URL;\n}\n\nexport function resolveTokenBase(o: OAuthHostOptions): string {\n return o.tokenBaseUrl ?? o.oauthBaseUrl ?? DEFAULT_TOKEN_BASE_URL;\n}\n\nexport interface TokenSet {\n accessToken: string;\n refreshToken?: string;\n /** Epoch milliseconds at which the access token expires (if the server told us). */\n expiresAt?: number;\n scope?: string;\n tokenType?: string;\n}\n\ninterface RawTokenResponse {\n access_token: string;\n refresh_token?: string;\n expires_in?: number;\n scope?: string;\n token_type?: string;\n}\n\nfunction toTokenSet(raw: RawTokenResponse, now: number): TokenSet {\n return {\n accessToken: raw.access_token,\n refreshToken: raw.refresh_token,\n expiresAt: raw.expires_in ? now + raw.expires_in * 1000 : undefined,\n scope: raw.scope,\n tokenType: raw.token_type,\n };\n}\n\nasync function postToken(\n oauthBaseUrl: string,\n params: Record<string, string>,\n fetchImpl: typeof fetch,\n now: () => number,\n): Promise<TokenSet> {\n const res = await fetchImpl(`${oauthBaseUrl}/token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams(params).toString(),\n });\n if (!res.ok) {\n let detail = \"\";\n try {\n detail = JSON.stringify(await res.json());\n } catch {\n detail = await res.text().catch(() => \"\");\n }\n throw new Error(`OAuth token request failed (${res.status}): ${detail}`);\n }\n return toTokenSet((await res.json()) as RawTokenResponse, now());\n}\n\n// ---- PKCE (authorization_code) ----\n\nexport interface Pkce {\n codeVerifier: string;\n codeChallenge: string;\n codeChallengeMethod: \"S256\";\n}\n\nfunction base64Url(buf: Buffer): string {\n return buf.toString(\"base64\").replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n/** Generate a PKCE verifier/challenge pair (RFC 7636, S256). */\nexport function generatePkce(): Pkce {\n const codeVerifier = base64Url(randomBytes(32));\n const codeChallenge = base64Url(createHash(\"sha256\").update(codeVerifier).digest());\n return { codeVerifier, codeChallenge, codeChallengeMethod: \"S256\" };\n}\n\nexport interface AuthorizationUrlOptions extends OAuthHostOptions {\n clientId: string;\n redirectUri: string;\n scopes: string[];\n /** Opaque CSRF token you generate and verify on callback. */\n state: string;\n pkce: Pkce;\n}\n\n/** Build the URL to redirect a user to for the authorization_code + PKCE flow. */\nexport function createAuthorizationUrl(opts: AuthorizationUrlOptions): string {\n // Explicit override wins; otherwise pick the host from the client_id mode\n // (pk_test_ → sandbox consent host, else live). The token host is separate.\n const base = opts.authorizeBaseUrl ?? opts.oauthBaseUrl ?? defaultAuthorizeBase(opts.clientId);\n const q = new URLSearchParams({\n response_type: \"code\",\n client_id: opts.clientId,\n redirect_uri: opts.redirectUri,\n scope: opts.scopes.join(\" \"),\n state: opts.state,\n code_challenge: opts.pkce.codeChallenge,\n code_challenge_method: opts.pkce.codeChallengeMethod,\n });\n return `${base}/authorize?${q.toString()}`;\n}\n\nexport interface ExchangeCodeOptions extends OAuthHostOptions {\n clientId: string;\n /** Public (PKCE) clients omit this; confidential clients pass it. */\n clientSecret?: string;\n code: string;\n redirectUri: string;\n codeVerifier: string;\n fetch?: typeof fetch;\n now?: () => number;\n}\n\n/** Exchange an authorization code (+ PKCE verifier) for a token set. */\nexport function exchangeCode(opts: ExchangeCodeOptions): Promise<TokenSet> {\n const params: Record<string, string> = {\n grant_type: \"authorization_code\",\n client_id: opts.clientId,\n code: opts.code,\n redirect_uri: opts.redirectUri,\n code_verifier: opts.codeVerifier,\n };\n if (opts.clientSecret) params.client_secret = opts.clientSecret;\n return postToken(resolveTokenBase(opts), params, opts.fetch ?? fetch, opts.now ?? Date.now);\n}\n\n// ---- client_credentials (server-to-server, read:public) ----\n\nexport interface ClientCredentialsOptions extends OAuthHostOptions {\n clientId: string;\n clientSecret: string;\n scopes?: string[];\n fetch?: typeof fetch;\n now?: () => number;\n}\n\nexport function clientCredentialsGrant(opts: ClientCredentialsOptions): Promise<TokenSet> {\n const params: Record<string, string> = {\n grant_type: \"client_credentials\",\n client_id: opts.clientId,\n client_secret: opts.clientSecret,\n };\n if (opts.scopes?.length) params.scope = opts.scopes.join(\" \");\n return postToken(resolveTokenBase(opts), params, opts.fetch ?? fetch, opts.now ?? Date.now);\n}\n\n// ---- refresh with ROTATION ----\n\nexport interface RefreshOptions extends OAuthHostOptions {\n clientId: string;\n clientSecret?: string;\n refreshToken: string;\n fetch?: typeof fetch;\n now?: () => number;\n}\n\n/**\n * Refresh an access token. CRITICAL: the returned TokenSet carries a NEW refresh\n * token (rotation). The caller MUST persist it — reusing the old refresh token\n * after rotation results in a permanent 401. The client/TokenManager handles this.\n */\nexport function refreshToken(opts: RefreshOptions): Promise<TokenSet> {\n const params: Record<string, string> = {\n grant_type: \"refresh_token\",\n client_id: opts.clientId,\n refresh_token: opts.refreshToken,\n };\n if (opts.clientSecret) params.client_secret = opts.clientSecret;\n return postToken(resolveTokenBase(opts), params, opts.fetch ?? fetch, opts.now ?? Date.now);\n}\n","// Typed errors mapped from the REAL Wefunder error envelope. Confirmed against\n// api/v2/base_controller.rb#render_error (and the doorkeeper render options):\n// { \"error\": { \"type\", \"message\", \"details\"?, \"request_id\", \"remediation\"? } }\n// NOTE: request_id and remediation are NESTED under `error` (not top-level) — the\n// spec's Error schema models neither, but the runtime always emits request_id.\n\nexport interface WefunderErrorBody {\n error?: {\n type?: string;\n message?: string;\n details?: unknown;\n request_id?: string;\n remediation?: string;\n };\n // Defensive: some envelopes (e.g. *WithMeta success meta) carry request_id here.\n request_id?: string;\n}\n\n/** Response header carrying the partner-facing request id (Stripe-style `req_…`). */\nexport const REQUEST_ID_HEADER = \"x-wf-request-id\";\n\n/** Prefer the X-Wf-Request-Id response header; fall back to a body-derived id. */\nexport function requestIdFrom(response: Response | undefined, bodyRequestId: string | undefined): string | undefined {\n return response?.headers.get(REQUEST_ID_HEADER) ?? bodyRequestId;\n}\n\nexport class WefunderError extends Error {\n readonly status: number;\n readonly type: string;\n readonly requestId?: string;\n readonly details?: unknown;\n /** Server-provided hint on how to resolve the error, when present. */\n readonly remediation?: string;\n /** Documentation pointer surfaced to developers in stack traces / logs. */\n readonly documentationUrl = \"https://docs.wefunder.com/api-reference\";\n\n constructor(args: {\n status: number;\n type: string;\n message: string;\n requestId?: string;\n details?: unknown;\n remediation?: string;\n }) {\n super(args.message);\n this.name = \"WefunderError\";\n this.status = args.status;\n this.type = args.type;\n this.requestId = args.requestId;\n this.details = args.details;\n this.remediation = args.remediation;\n }\n}\n\n/** Raised when token refresh is needed but no refresh token / refresher is configured. */\nexport class WefunderAuthError extends WefunderError {\n constructor(message: string) {\n super({ status: 401, type: \"unauthorized\", message });\n this.name = \"WefunderAuthError\";\n }\n}\n\n/**\n * Build a WefunderError from a failed Response. Reads the typed envelope from the\n * body; falls back gracefully when the body isn't the expected shape.\n */\nexport async function errorFromResponse(response: Response): Promise<WefunderError> {\n let body: WefunderErrorBody | undefined;\n try {\n body = (await response.clone().json()) as WefunderErrorBody;\n } catch {\n // non-JSON body (e.g. an HTML 502 from the edge) — keep body undefined\n }\n const err = body?.error ?? {};\n return new WefunderError({\n status: response.status,\n type: err.type ?? \"api_error\",\n message: err.message ?? response.statusText ?? \"Request failed\",\n // X-Wf-Request-Id is set on every authenticated response (base_controller.rb),\n // so it's present even when the body isn't JSON (e.g. an HTML 502 from the edge),\n // unlike the nested error.request_id. Prefer the header; fall back to the body.\n requestId: requestIdFrom(response, err.request_id ?? body?.request_id),\n details: err.details,\n remediation: err.remediation,\n });\n}\n","// Holds the live token state and owns token recovery + persistence. Two recovery\n// strategies, picked automatically:\n// - refresh_token (user flows): rotates — every refresh returns a NEW refresh\n// token, persisted BEFORE the next request can use it (the CRITICAL invariant).\n// - re-mint (client_credentials): cc tokens have NO refresh token, but a client\n// built via fromClientCredentials holds the grant inputs, so it can mint a fresh\n// token on expiry/401 instead of throwing. (Stress-test finding A.)\n// Either way, concurrent callers share one in-flight promise so a burst of 401s\n// fires a single recovery (no rotation race / thundering herd).\n\nimport { refreshToken, resolveTokenBase, type TokenSet, type OAuthHostOptions } from \"./oauth.js\";\nimport { WefunderAuthError } from \"./errors.js\";\n\n/** Pluggable persistence for the rotating token set (DB row, secrets manager, etc.). */\nexport interface TokenStore {\n load?(): Promise<TokenSet | undefined> | TokenSet | undefined;\n save(tokens: TokenSet): Promise<void> | void;\n}\n\nexport interface TokenManagerOptions extends OAuthHostOptions {\n tokens: TokenSet;\n clientId?: string;\n clientSecret?: string;\n /**\n * For client_credentials clients: mint a fresh token from the stored grant inputs.\n * When set (and there's no refresh token), this is the recovery strategy.\n */\n reMint?: () => Promise<TokenSet>;\n /** Called with the new TokenSet on every successful recovery (rotation or re-mint). */\n onTokenRefresh?: (tokens: TokenSet) => void | Promise<void>;\n store?: TokenStore;\n fetch?: typeof fetch;\n now?: () => number;\n /** Refresh proactively when the access token is within this many ms of expiry. */\n expiryLeewayMs?: number;\n}\n\nexport class TokenManager {\n #tokens: TokenSet;\n readonly #clientId?: string;\n readonly #clientSecret?: string;\n readonly #reMint?: () => Promise<TokenSet>;\n readonly #tokenBaseUrl: string;\n readonly #onTokenRefresh?: (tokens: TokenSet) => void | Promise<void>;\n readonly #store?: TokenStore;\n readonly #fetch: typeof fetch;\n readonly #now: () => number;\n readonly #leeway: number;\n #inflight: Promise<TokenSet> | undefined;\n\n constructor(opts: TokenManagerOptions) {\n this.#tokens = opts.tokens;\n this.#clientId = opts.clientId;\n this.#clientSecret = opts.clientSecret;\n this.#reMint = opts.reMint;\n this.#tokenBaseUrl = resolveTokenBase(opts);\n this.#onTokenRefresh = opts.onTokenRefresh;\n this.#store = opts.store;\n this.#fetch = opts.fetch ?? fetch;\n this.#now = opts.now ?? Date.now;\n this.#leeway = opts.expiryLeewayMs ?? 30_000;\n }\n\n get current(): TokenSet {\n return this.#tokens;\n }\n\n /** True if the manager can recover an expired token (rotate a refresh token or re-mint). */\n get canRefresh(): boolean {\n return Boolean((this.#tokens.refreshToken && this.#clientId) || this.#reMint);\n }\n\n /** Returns a valid access token, refreshing proactively if it's expired/near-expiry. */\n async getAccessToken(): Promise<string> {\n const { expiresAt } = this.#tokens;\n if (expiresAt !== undefined && this.#now() >= expiresAt - this.#leeway && this.canRefresh) {\n await this.refresh();\n }\n return this.#tokens.accessToken;\n }\n\n /**\n * Recover an expired/rejected token (e.g. after a 401): rotates the refresh token\n * if there is one, otherwise re-mints (client_credentials). Coalesces concurrent\n * calls into one network round-trip, then persists. Returns the new token set.\n */\n async refresh(): Promise<TokenSet> {\n if (this.#inflight) return this.#inflight;\n const strategy = this.#recoveryStrategy();\n if (!strategy) {\n throw new WefunderAuthError(\n \"Access token expired and no refresh token / re-mint capability is configured.\",\n );\n }\n this.#inflight = (async () => {\n const next = await strategy();\n this.#tokens = next;\n await this.#store?.save(next);\n await this.#onTokenRefresh?.(next);\n return next;\n })();\n try {\n return await this.#inflight;\n } finally {\n this.#inflight = undefined;\n }\n }\n\n // Pick the recovery strategy: refresh_token rotation, else cc re-mint, else none.\n #recoveryStrategy(): (() => Promise<TokenSet>) | undefined {\n const refreshTokenValue = this.#tokens.refreshToken;\n if (refreshTokenValue && this.#clientId) {\n const clientId = this.#clientId;\n return async () => {\n const next = await refreshToken({\n clientId,\n clientSecret: this.#clientSecret,\n refreshToken: refreshTokenValue,\n tokenBaseUrl: this.#tokenBaseUrl,\n fetch: this.#fetch,\n now: this.#now,\n });\n // Some servers omit a fresh refresh_token on rotation-disabled flows;\n // keep the previous one rather than dropping our ability to refresh.\n if (!next.refreshToken) next.refreshToken = refreshTokenValue;\n return next;\n };\n }\n return this.#reMint;\n }\n}\n","// Lazy auto-pagination. The cursor is treated as an OPAQUE token (plan §4.1 #5):\n// different endpoints back it with an int id, an ISO timestamp, or an offset, so we\n// never inspect or arithmetic it — we just feed `meta.next_cursor` back verbatim.\n// Streams items one page at a time (never buffers the whole result set).\n\nexport type Cursor = string | number;\n\nexport interface Page<T> {\n data?: T[] | null;\n meta?: {\n has_more?: boolean;\n next_cursor?: Cursor | null;\n [k: string]: unknown;\n };\n}\n\n/** Fetches a single page given an opaque cursor (undefined = first page). */\nexport type PageFetcher<T> = (cursor?: Cursor) => Promise<Page<T>>;\n\n/** Yields every item across all pages, lazily. */\nexport async function* paginate<T>(fetchPage: PageFetcher<T>): AsyncGenerator<T> {\n let cursor: Cursor | undefined;\n const seen = new Set<Cursor>();\n for (;;) {\n const page = await fetchPage(cursor);\n for (const item of page.data ?? []) yield item;\n\n const meta = page.meta ?? {};\n const next = meta.next_cursor;\n // Stop conditions: explicit has_more=false, no next cursor, or a cursor that\n // doesn't advance (defensive guard against an endpoint that loops).\n if (meta.has_more === false) return;\n if (next === undefined || next === null) return;\n if (seen.has(next)) return;\n seen.add(next);\n cursor = next;\n }\n}\n\n/** Collect all items into an array. Convenience over `paginate` for small result sets. */\nexport async function collect<T>(fetchPage: PageFetcher<T>): Promise<T[]> {\n const out: T[] = [];\n for await (const item of paginate(fetchPage)) out.push(item);\n return out;\n}\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type {\n Client,\n ClientMeta,\n Options as Options2,\n RequestResult,\n TDataShape,\n} from \"./client\";\nimport { client } from \"./client.gen\";\nimport type {\n ApproveSyndicateMemberData,\n ApproveSyndicateMemberErrors,\n ApproveSyndicateMemberResponses,\n CloseSyndicateDealData,\n CloseSyndicateDealErrors,\n CloseSyndicateDealResponses,\n CreateInstallationData,\n CreateInstallationErrors,\n CreateInstallationResponses,\n CreateInstallationTokenData,\n CreateInstallationTokenErrors,\n CreateInstallationTokenResponses,\n CreateIntentData,\n CreateIntentErrors,\n CreateIntentResponses,\n CreatePartnerInviteData,\n CreatePartnerInviteErrors,\n CreatePartnerInviteResponses,\n CreateWebhookEndpointData,\n CreateWebhookEndpointErrors,\n CreateWebhookEndpointResponses,\n CreateWebhookSubscriptionData,\n CreateWebhookSubscriptionErrors,\n CreateWebhookSubscriptionResponses,\n DeleteWebhookEndpointData,\n DeleteWebhookEndpointErrors,\n DeleteWebhookEndpointResponses,\n DeleteWebhookSubscriptionData,\n DeleteWebhookSubscriptionErrors,\n DeleteWebhookSubscriptionResponses,\n DemoteSyndicateMemberData,\n DemoteSyndicateMemberErrors,\n DemoteSyndicateMemberResponses,\n ExportSyndicateMembersCsvData,\n ExportSyndicateMembersCsvErrors,\n ExportSyndicateMembersCsvResponses,\n FinalizeSyndicateDealData,\n FinalizeSyndicateDealErrors,\n FinalizeSyndicateDealResponses,\n FollowCompanyData,\n FollowCompanyErrors,\n FollowCompanyResponses,\n GetAttributionMeData,\n GetAttributionMeErrors,\n GetAttributionMeResponses,\n GetAttributionStatsData,\n GetAttributionStatsErrors,\n GetAttributionStatsResponses,\n GetCompanyData,\n GetCompanyDisclosuresData,\n GetCompanyDisclosuresErrors,\n GetCompanyDisclosuresResponses,\n GetCompanyErrors,\n GetCompanyPitchData,\n GetCompanyPitchErrors,\n GetCompanyPitchResponses,\n GetCompanyResponses,\n GetCompanyUpdateData,\n GetCompanyUpdateErrors,\n GetCompanyUpdateResponses,\n GetCurrentUserData,\n GetCurrentUserErrors,\n GetCurrentUserResponses,\n GetInstallationData,\n GetInstallationErrors,\n GetInstallationResponses,\n GetIntentData,\n GetIntentErrors,\n GetIntentResponses,\n GetInvestmentData,\n GetInvestmentErrors,\n GetInvestmentResponses,\n GetOfferingData,\n GetOfferingErrors,\n GetOfferingResponses,\n GetOfferingStatsData,\n GetOfferingStatsErrors,\n GetOfferingStatsResponses,\n GetPortfolioData,\n GetPortfolioErrors,\n GetPortfolioResponses,\n GetSyndicateData,\n GetSyndicateDealData,\n GetSyndicateDealErrors,\n GetSyndicateDealResponses,\n GetSyndicateErrors,\n GetSyndicatePortfolioData,\n GetSyndicatePortfolioErrors,\n GetSyndicatePortfolioResponses,\n GetSyndicateResponses,\n GetSyndicateStatisticsData,\n GetSyndicateStatisticsErrors,\n GetSyndicateStatisticsResponses,\n GetWebhookEndpointData,\n GetWebhookEndpointErrors,\n GetWebhookEndpointResponses,\n GetWebhookSubscriptionData,\n GetWebhookSubscriptionErrors,\n GetWebhookSubscriptionResponses,\n HideSyndicateMemberData,\n HideSyndicateMemberErrors,\n HideSyndicateMemberResponses,\n InviteSyndicateMemberData,\n InviteSyndicateMemberErrors,\n InviteSyndicateMemberResponses,\n ListActivityData,\n ListActivityErrors,\n ListActivityResponses,\n ListAttributedInvestmentsData,\n ListAttributedInvestmentsErrors,\n ListAttributedInvestmentsResponses,\n ListAttributionCampaignsData,\n ListAttributionCampaignsErrors,\n ListAttributionCampaignsResponses,\n ListCampaignsData,\n ListCampaignsErrors,\n ListCampaignsResponses,\n ListCompanyInvestmentChangesData,\n ListCompanyInvestmentChangesErrors,\n ListCompanyInvestmentChangesResponses,\n ListCompanyQuestionsData,\n ListCompanyQuestionsErrors,\n ListCompanyQuestionsResponses,\n ListCompanyUpdatesData,\n ListCompanyUpdatesErrors,\n ListCompanyUpdatesResponses,\n ListConnectedAppsData,\n ListConnectedAppsErrors,\n ListConnectedAppsResponses,\n ListEligibleInstallTargetsData,\n ListEligibleInstallTargetsErrors,\n ListEligibleInstallTargetsResponses,\n ListFollowedCompaniesData,\n ListFollowedCompaniesErrors,\n ListFollowedCompaniesResponses,\n ListInstallationsData,\n ListInstallationsErrors,\n ListInstallationsResponses,\n ListIntentsData,\n ListIntentsErrors,\n ListIntentsResponses,\n ListInvestmentsData,\n ListInvestmentsErrors,\n ListInvestmentsResponses,\n ListMyCompaniesData,\n ListMyCompaniesErrors,\n ListMyCompaniesResponses,\n ListOfferingsData,\n ListOfferingsErrors,\n ListOfferingsResponses,\n ListPartnerInvitesData,\n ListPartnerInvitesErrors,\n ListPartnerInvitesResponses,\n ListPortfolioPositionsData,\n ListPortfolioPositionsErrors,\n ListPortfolioPositionsResponses,\n ListSyndicateDealInvestorsData,\n ListSyndicateDealInvestorsErrors,\n ListSyndicateDealInvestorsResponses,\n ListSyndicateDealsData,\n ListSyndicateDealsErrors,\n ListSyndicateDealsResponses,\n ListSyndicateMemberInvestmentsData,\n ListSyndicateMemberInvestmentsErrors,\n ListSyndicateMemberInvestmentsResponses,\n ListSyndicateMembersData,\n ListSyndicateMembersErrors,\n ListSyndicateMembersResponses,\n ListSyndicatePortfolioPositionsData,\n ListSyndicatePortfolioPositionsErrors,\n ListSyndicatePortfolioPositionsResponses,\n ListSyndicatesData,\n ListSyndicatesErrors,\n ListSyndicatesResponses,\n ListWebhookEndpointsData,\n ListWebhookEndpointsErrors,\n ListWebhookEndpointsResponses,\n ListWebhookSubscriptionsData,\n ListWebhookSubscriptionsErrors,\n ListWebhookSubscriptionsResponses,\n PreviewIntentData,\n PreviewIntentErrors,\n PreviewIntentResponses,\n PromoteSyndicateMemberData,\n PromoteSyndicateMemberErrors,\n PromoteSyndicateMemberResponses,\n ReactivateWebhookSubscriptionData,\n ReactivateWebhookSubscriptionErrors,\n ReactivateWebhookSubscriptionResponses,\n ReenableWebhookEndpointData,\n ReenableWebhookEndpointErrors,\n ReenableWebhookEndpointResponses,\n RegenerateWebhookSecretData,\n RegenerateWebhookSecretErrors,\n RegenerateWebhookSecretResponses,\n RegisterAsPartnerData,\n RegisterAsPartnerErrors,\n RegisterAsPartnerResponses,\n RemoveSyndicateMemberData,\n RemoveSyndicateMemberErrors,\n ReorderSyndicateMembersData,\n ReorderSyndicateMembersErrors,\n ReorderSyndicateMembersResponses,\n ResendSyndicateInviteData,\n ResendSyndicateInviteErrors,\n ResendSyndicateInviteResponses,\n RestoreSyndicateMemberData,\n RestoreSyndicateMemberErrors,\n RestoreSyndicateMemberResponses,\n RevokeConnectedAppData,\n RevokeConnectedAppErrors,\n RevokeConnectedAppResponses,\n RevokeInstallationData,\n RevokeInstallationErrors,\n RevokeInstallationResponses,\n RevokePartnerInviteData,\n RevokePartnerInviteErrors,\n RevokePartnerInviteResponses,\n RotateWebhookEndpointSecretData,\n RotateWebhookEndpointSecretErrors,\n RotateWebhookEndpointSecretResponses,\n SearchCompaniesData,\n SearchCompaniesErrors,\n SearchCompaniesResponses,\n TestWebhookEndpointData,\n TestWebhookEndpointErrors,\n TestWebhookEndpointResponses,\n TestWebhookSubscriptionData,\n TestWebhookSubscriptionErrors,\n TestWebhookSubscriptionResponses,\n UnfollowCompanyData,\n UnfollowCompanyErrors,\n UnfollowCompanyResponses,\n UpdateSyndicateData,\n UpdateSyndicateErrors,\n UpdateSyndicateMemberData,\n UpdateSyndicateMemberErrors,\n UpdateSyndicateMemberResponses,\n UpdateSyndicateResponses,\n UpdateWebhookEndpointData,\n UpdateWebhookEndpointErrors,\n UpdateWebhookEndpointResponses,\n} from \"./types.gen\";\n\nexport type Options<\n TData extends TDataShape = TDataShape,\n ThrowOnError extends boolean = boolean,\n TResponse = unknown,\n> = Options2<TData, ThrowOnError, TResponse> & {\n /**\n * You can provide a client instance returned by `createClient()` instead of\n * individual options. This might be also useful if you want to implement a\n * custom client.\n */\n client?: Client;\n /**\n * You can pass arbitrary values through the `meta` object. This can be\n * used to access values that aren't defined as part of the SDK function.\n */\n meta?: keyof ClientMeta extends never ? Record<string, unknown> : ClientMeta;\n};\n\n/**\n * List public offerings\n *\n * Returns the offerings shown on wefunder.com/explore — the curated set of companies that\n * meet Wefunder's discoverability bar (a soft-confirmed traction threshold plus approval),\n * **one offering per company**. An \"offering\" is a fundraise, addressed by its id\n * (`ofr_...`).\n *\n * **Public view (`read:public`).** Reachable with either a server-side (client_credentials)\n * token or a user access token. Private rounds (e.g. Reg D 506(b)) are never listed, and\n * low-traction or unapproved companies are excluded — exactly as they are on the website\n * for a logged-out visitor.\n *\n * **Logged-in view (`read:explore`).** A user access token carrying `read:explore` gets\n * what *that user* sees on wefunder.com/explore: the public offerings plus any the user\n * qualifies for (accredited-only / Vault deals, invited private rounds), each checked\n * against the same visibility policy the website applies. The response is a strict\n * superset of the public one — same fields and ids — with two extra attributes,\n * `publicly_visible` and `invested`, and `meta.personalized: true`. A server-side key can\n * never hold `read:explore`; a token with `read:explore` but no resolvable user gets the\n * public view.\n *\n * Order with `sort` (default: most raised); paginate with `cursor`. `meta.total_count` is\n * the number of offerings across all pages, after filters.\n *\n * **Filters** are objective, per-offering terms — exemption family, security type,\n * TTW vs. live, minimum investment ceiling, close date, amount raised floor. The response\n * echoes the applied set in `meta.filters`. An out-of-vocabulary value is a `400` naming\n * the accepted values. There are deliberately no relevance, quality, or ranking criteria.\n *\n * Use this endpoint to:\n * - Discover and monitor active deals\n * - Build deal aggregators and public listings\n *\n */\nexport const listOfferings = <ThrowOnError extends boolean = false>(\n options?: Options<ListOfferingsData, ThrowOnError>,\n): RequestResult<ListOfferingsResponses, ListOfferingsErrors, ThrowOnError> =>\n (options?.client ?? client).get<\n ListOfferingsResponses,\n ListOfferingsErrors,\n ThrowOnError\n >({\n querySerializer: {\n parameters: {\n industry: { array: { explode: false } },\n business_model: { array: { explode: false } },\n },\n },\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/explore\",\n ...options,\n });\n\n/**\n * Get a public offering\n *\n * Retrieves a single offering by its id (`ofr_...`).\n *\n * With `read:public`, a valid id for a non-public offering (e.g. a private Reg D 506(b)\n * round) returns `404` — having an id does not make an offering publicly resolvable. With\n * `read:explore` on a user access token, the offering resolves if *that user* may see it on\n * wefunder.com (e.g. an accredited-only or invited round), and the response gains\n * `publicly_visible` and `invested`.\n *\n */\nexport const getOffering = <ThrowOnError extends boolean = false>(\n options: Options<GetOfferingData, ThrowOnError>,\n): RequestResult<GetOfferingResponses, GetOfferingErrors, ThrowOnError> =>\n (options.client ?? client).get<\n GetOfferingResponses,\n GetOfferingErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/offerings/{external_id}\",\n ...options,\n });\n\n/**\n * Get a company's public Form C disclosures\n *\n * The Details tab of the company's Wefunder page as structured data — the company's own\n * Form C disclosures, section for section: financial statements for the fiscal years on\n * file, the page's ratios, the founder's current-position disclosure (cash on hand, monthly\n * revenue / costs / burn), the financial-condition narrative, document links, risks, use of\n * funds, directors and officers, 20%+ holders, capital structure, prior offerings, outstanding\n * notes and debts, and related-party transactions.\n *\n * Same \"who has a page\" rule as `GET /companies/{id}`. The round read is the page's own: the\n * display round for the viewer, swapped for its concurrent Reg CF sibling on a Reg D round,\n * and only when it is a Reg CF / ECSP round with a Form C. A company with no such round has\n * no details tab on the site and answers `404` with `error.type: no_disclosures` — distinct\n * from an unknown or hidden company. A section the company hides on the site is `null`.\n *\n * Money is USD as decimal strings; ratios are percentages as decimal strings. Everything here\n * is the issuer's own disclosure, served as filed, not a Wefunder assessment.\n *\n */\nexport const getCompanyDisclosures = <ThrowOnError extends boolean = false>(\n options: Options<GetCompanyDisclosuresData, ThrowOnError>,\n): RequestResult<\n GetCompanyDisclosuresResponses,\n GetCompanyDisclosuresErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n GetCompanyDisclosuresResponses,\n GetCompanyDisclosuresErrors,\n ThrowOnError\n >({\n querySerializer: {\n parameters: { sections: { array: { explode: false } } },\n },\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/companies/{id}/disclosures\",\n ...options,\n });\n\n/**\n * Get a company's pitch\n *\n * The Overview tab's pitch as structured data: the story as ordered blocks (`heading`,\n * `paragraph`, `list`, `image`, `video`, `footnote`), plus the perk tiers of the round the page\n * shows the viewer. Images and embedded videos keep their place in the document with an absolute\n * URL, because founders publish perk tiers, stretch goals, timelines, and charts as pictures\n * (typically with no alt text) and a plain-text rendering would drop them.\n *\n * What is parsed is what the page renders: the story passes through the site's own sanitizer\n * first, so an embed the page refuses (a host off its allowlist, a `javascript:` URL) is never\n * served here either. Same \"who has a page\" rule and round chooser as `GET /companies/{id}`.\n * A site-public company with no round the viewer may see still has a pitch (`perks: null`).\n * `perks.described_in_pitch` is a heuristic: true when the structured perk list is a placeholder\n * (\"See investor overview page\", or one identical sentence on every tier) and the real tiers are\n * in the story's images.\n *\n * `authored_by` says who wrote the story: `company` (the issuer's own words and imagery, not a\n * Wefunder assessment) or `wefunder` (a Wefunder-prepared deal memo the company did not\n * participate in; `disclaimer` carries the page's notice). A pitch can run to ~70 KB; use\n * `sections` to ask for less.\n *\n */\nexport const getCompanyPitch = <ThrowOnError extends boolean = false>(\n options: Options<GetCompanyPitchData, ThrowOnError>,\n): RequestResult<\n GetCompanyPitchResponses,\n GetCompanyPitchErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n GetCompanyPitchResponses,\n GetCompanyPitchErrors,\n ThrowOnError\n >({\n querySerializer: {\n parameters: { sections: { array: { explode: false } } },\n },\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/companies/{id}/pitch\",\n ...options,\n });\n\n/**\n * List a company's posts\n *\n * The company page's Posts tab as data: the published updates, notes, and spotlights the\n * viewer may see, pinned first then newest, with a plain-text excerpt each. With\n * `read:explore` the viewer is the authorizing user, so a follower or investor sees the\n * community- and investors-only posts the site shows them; with `read:public` it is the\n * anonymous view. Same query as the tab (`FeedItem.viewable_by`); investments, Q&A threads,\n * and investor quotes belong to other tabs and are not here. Fetch one post in full with\n * `GET /companies/{id}/updates/{update_id}`. Posts are the issuer's own words.\n *\n */\nexport const listCompanyUpdates = <ThrowOnError extends boolean = false>(\n options: Options<ListCompanyUpdatesData, ThrowOnError>,\n): RequestResult<\n ListCompanyUpdatesResponses,\n ListCompanyUpdatesErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n ListCompanyUpdatesResponses,\n ListCompanyUpdatesErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/companies/{id}/updates\",\n ...options,\n });\n\n/**\n * Get one company post in full\n *\n * One post with its full plain-text content, by the id the list returned. Same visibility as the list; a post the tab would not show this viewer is a 404.\n */\nexport const getCompanyUpdate = <ThrowOnError extends boolean = false>(\n options: Options<GetCompanyUpdateData, ThrowOnError>,\n): RequestResult<\n GetCompanyUpdateResponses,\n GetCompanyUpdateErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n GetCompanyUpdateResponses,\n GetCompanyUpdateErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/companies/{id}/updates/{update_id}\",\n ...options,\n });\n\n/**\n * List a company's investor questions and answers\n *\n * The company page's Ask tab as data: the questions investors asked and the answers, as the\n * tab lists them for this viewer (the same repository and visibility as the site). Like the tab,\n * questions default to the current raise — those asked since it opened (`meta.questions_since`);\n * `past_raises=true` includes every raise, which the site offers to any visitor because\n * past-raise questions are public. `sort` is the tab's dropdown: `relevance` (default:\n * highlighted, then answered, then most liked), `recent`, `upvoted`, `unanswered`. Text is plain.\n * Questions and answers carry their id (`cmt_...`); the integer key never leaves the API.\n * Answers are the founders' own words.\n *\n * `q` searches question and answer text (Postgres full text: quoted phrases and `-word` work;\n * one- or two-word queries also prefix-match) and replaces the sort with match rank —\n * `meta.sort` is then `search` and each result's `match` says whether its question or an\n * answer matched. `unanswered_by_team=true` keeps only questions with no live answer from the\n * company's team (the founder's queue; the `unanswered` sort merely orders by whether anyone\n * replied).\n *\n */\nexport const listCompanyQuestions = <ThrowOnError extends boolean = false>(\n options: Options<ListCompanyQuestionsData, ThrowOnError>,\n): RequestResult<\n ListCompanyQuestionsResponses,\n ListCompanyQuestionsErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n ListCompanyQuestionsResponses,\n ListCompanyQuestionsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/companies/{id}/questions\",\n ...options,\n });\n\n/**\n * Search companies by name\n *\n * The wefunder.com search bar, companies only. Same Algolia request, same result ordering,\n * and same page size as the site's top bar, so the results are what a visitor typing the\n * same text would see, in that order — companies raising now and companies funded in the\n * past, whether or not they appear on `/explore`. The order is the site's search order\n * (match quality first, then the site's tie-breaks); nothing here recommends.\n *\n * Each result carries the company's `co_` id for `GET /companies/{id}`. With `read:explore`\n * the accreditation gate matches the authorizing user (an accredited viewer sees the\n * accredited-only companies the site would show them); with `read:public` it is the\n * anonymous view.\n *\n */\nexport const searchCompanies = <ThrowOnError extends boolean = false>(\n options: Options<SearchCompaniesData, ThrowOnError>,\n): RequestResult<\n SearchCompaniesResponses,\n SearchCompaniesErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n SearchCompaniesResponses,\n SearchCompaniesErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/companies/search\",\n ...options,\n });\n\n/**\n * Get a company page\n *\n * The company page behind an offering, as structured data — the \"click a company\" step after\n * `/explore`. Addressed by the `co_...` id every offering carries in `company.id`.\n *\n * Keeps apart the three raised numbers the page shows and readers conflate:\n * `current_raise.amount_raised` (this campaign's live rounds combined, on Wefunder),\n * `past_rounds[]` (prior rounds the page lists, each tagged `source: wefunder` for rounds\n * observed here or `reported` for founder-disclosed off-platform rounds), and\n * `totals.profile_total_raised` (the number on the page's ticker bar). Every figure comes\n * from the same policy the page uses, so the API never disagrees with the site.\n *\n * **Who has a page.** Every company whose profile wefunder.com lists publicly — the same set\n * the site's search bar returns (published, not invite-only, searchable or with a live Form C;\n * accredited-only companies need an accredited viewer) — plus the `/explore` set. A funded\n * company, or one the viewer may see no round of, renders with `raising: false` and\n * `current_raise: null`; its history is in `wefunder_rounds`. **Logged-in view\n * (`read:explore`)** additionally covers the vault / syndicate-led companies the site shows an\n * accredited viewer, and the round described is the one the page would show that viewer. A\n * valid id for a company outside the viewer's set is a `404`, never a partial payload.\n *\n */\nexport const getCompany = <ThrowOnError extends boolean = false>(\n options: Options<GetCompanyData, ThrowOnError>,\n): RequestResult<GetCompanyResponses, GetCompanyErrors, ThrowOnError> =>\n (options.client ?? client).get<\n GetCompanyResponses,\n GetCompanyErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/companies/{id}\",\n ...options,\n });\n\n/**\n * Get current user profile\n *\n * Retrieves the profile information for the currently authenticated user. This endpoint returns\n * basic user details including name, email, and account status.\n *\n * Use this endpoint to:\n * - Display user information in your application\n * - Verify the identity of the authenticated user\n * - Check user account status and permissions\n *\n * The response includes the user's unique ID which can be used to reference the user in other API calls.\n *\n */\nexport const getCurrentUser = <ThrowOnError extends boolean = false>(\n options?: Options<GetCurrentUserData, ThrowOnError>,\n): RequestResult<GetCurrentUserResponses, GetCurrentUserErrors, ThrowOnError> =>\n (options?.client ?? client).get<\n GetCurrentUserResponses,\n GetCurrentUserErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/users/me\",\n ...options,\n });\n\n/**\n * List the companies you edit\n *\n * The companies the authenticated user is a founder or team member of — precisely the\n * companies the founder-scoped endpoints under `/companies/{company_id}/...` (dashboard,\n * investors, fundraises) will accept. Anyone else's company returns 403 there, so call this\n * first to learn which `co_` ids you hold. Not paginated.\n *\n * `raising` is true when the company has a round currently accepting investments or\n * reservations. `roles` are the user's roles on the company (`founder`, `employee`, ...).\n *\n */\nexport const listMyCompanies = <ThrowOnError extends boolean = false>(\n options?: Options<ListMyCompaniesData, ThrowOnError>,\n): RequestResult<\n ListMyCompaniesResponses,\n ListMyCompaniesErrors,\n ThrowOnError\n> =>\n (options?.client ?? client).get<\n ListMyCompaniesResponses,\n ListMyCompaniesErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/users/me/companies\",\n ...options,\n });\n\n/**\n * List the companies you follow\n *\n * The authenticated user's watchlist — the companies they follow on wefunder.com (the same\n * rows the site's Follow button writes), newest first. Each entry is in the search-result\n * shape (`co_` id, name, tagline, URL, logo, `raising`, `profile_available`) plus\n * `followed_at`. The list owner sees every company they follow.\n *\n */\nexport const listFollowedCompanies = <ThrowOnError extends boolean = false>(\n options?: Options<ListFollowedCompaniesData, ThrowOnError>,\n): RequestResult<\n ListFollowedCompaniesResponses,\n ListFollowedCompaniesErrors,\n ThrowOnError\n> =>\n (options?.client ?? client).get<\n ListFollowedCompaniesResponses,\n ListFollowedCompaniesErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/users/me/follows\",\n ...options,\n });\n\n/**\n * Unfollow a company\n *\n * Unfollow the company for the authenticated user. Idempotent (`changed` is false when they were not following it). No visibility gate: a follow you hold is always undoable, even for a company since hidden. Requires `write:follows`.\n */\nexport const unfollowCompany = <ThrowOnError extends boolean = false>(\n options: Options<UnfollowCompanyData, ThrowOnError>,\n): RequestResult<\n UnfollowCompanyResponses,\n UnfollowCompanyErrors,\n ThrowOnError\n> =>\n (options.client ?? client).delete<\n UnfollowCompanyResponses,\n UnfollowCompanyErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/users/me/follows/{company_id}\",\n ...options,\n });\n\n/**\n * Follow a company\n *\n * Follow the company for the authenticated user — exactly what pressing Follow on its\n * Wefunder page does, side effects included (the company counts the user as a follower and\n * may be notified; the user receives the company's updates). Idempotent: following an\n * already-followed company returns `changed: false`. `404` for a company the site would not\n * show this user. Requires `write:follows`, which the user grants explicitly; it is never\n * implied by `read:mcp`.\n *\n */\nexport const followCompany = <ThrowOnError extends boolean = false>(\n options: Options<FollowCompanyData, ThrowOnError>,\n): RequestResult<FollowCompanyResponses, FollowCompanyErrors, ThrowOnError> =>\n (options.client ?? client).put<\n FollowCompanyResponses,\n FollowCompanyErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/users/me/follows/{company_id}\",\n ...options,\n });\n\n/**\n * List or sync investments\n *\n * The investment records the token may see, served from **published** state\n * (docs: *Investments: list, sync, retrieve*). The audience is the union of the companies\n * the token's user edits (their founder-visible records) and the user's own investments\n * (every applied record of theirs, whatever its status). Filters narrow within that\n * audience; they never widen it.\n *\n * Three ways to call it:\n * - **List** (no `cursor`, no `updated_since`): the current records, tombstones excluded,\n * ordered by investment. Page with `meta.next_cursor` while `meta.has_more`; the final\n * page's cursor is a sync cursor positioned at the moment the listing started.\n * - **Sync by cursor**: only the records whose published state changed since the cursor,\n * one record per investment, tombstones (`visible: false`, only `id`) included. Apply in\n * `cursor` order; always store `meta.next_cursor`.\n * - **Sync by time**: `updated_since=<ISO 8601>` is sugar for a cursor at the ledger position\n * just before that time (with a 60 s safety margin). The response is a normal sync page,\n * so continue with its `meta.next_cursor`.\n *\n * Records are eventually consistent (about ten minutes on the common paths); each carries\n * `observed_at`. `GET /investments/{id}` returns the same shape derived now. Investor\n * identity fields on other investors' records require `read:investors:pii`; a user always\n * sees their own. Money is integer minor units plus `amounts.currency`.\n *\n * **410 Gone** means the cursor or `updated_since` predates the 90-day retention window:\n * list again and replace your dataset. `status` cannot be combined with sync (a record\n * leaving the status would never be delivered).\n *\n */\nexport const listInvestments = <ThrowOnError extends boolean = false>(\n options?: Options<ListInvestmentsData, ThrowOnError>,\n): RequestResult<\n ListInvestmentsResponses,\n ListInvestmentsErrors,\n ThrowOnError\n> =>\n (options?.client ?? client).get<\n ListInvestmentsResponses,\n ListInvestmentsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/investments\",\n ...options,\n });\n\n/**\n * Retrieve an investment (current)\n *\n * The same record shape as the list, derived **now** from the investment rather than read\n * from published state, so an investor who just acted sees the change at once. Available\n * for any investment in the token's audience: the user's own (any status) or a\n * founder-visible investment on a company the user edits. `meta.published_matches` says\n * whether the published record already agrees; the sync stream converges within its\n * interval.\n *\n */\nexport const getInvestment = <ThrowOnError extends boolean = false>(\n options: Options<GetInvestmentData, ThrowOnError>,\n): RequestResult<GetInvestmentResponses, GetInvestmentErrors, ThrowOnError> =>\n (options.client ?? client).get<\n GetInvestmentResponses,\n GetInvestmentErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/investments/{id}\",\n ...options,\n });\n\n/**\n * Investment totals for an offering\n *\n * Count and committed amount of the founder-visible published records for one offering,\n * by status, from the same rows `GET /investments?offering_id=…` lists, so the two\n * reconcile. These are **not** the public campaign figures (the progress bar has its own\n * rules and sources); they are the sum of the records you can list. Requires the token's\n * user to edit the offering's company.\n *\n */\nexport const getOfferingStats = <ThrowOnError extends boolean = false>(\n options: Options<GetOfferingStatsData, ThrowOnError>,\n): RequestResult<\n GetOfferingStatsResponses,\n GetOfferingStatsErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n GetOfferingStatsResponses,\n GetOfferingStatsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/offerings/{offering_id}/stats\",\n ...options,\n });\n\n/**\n * Bootstrap or page investment changes for a company\n *\n * The Investment Delta API: keep a copy of a company's investment records in sync by\n * polling. Call without `cursor` to **bootstrap** (list every current record for the\n * company); every response carries `meta.next_cursor`; call again with that cursor to\n * receive only the records whose published state changed since. Records are the same\n * shape in both modes.\n *\n * - Records are **published state**, not live rows: Wefunder publishes a record when the\n * investment's founder-visible state changes, and serves exactly what was published.\n * - `visible: false` records are **tombstones**: the investment is no longer visible to the\n * company (canceled, converted to another round, hidden, or deleted). Delete your copy.\n * - Apply records in `cursor` order. `observed_at` is when the payload was observed, not a\n * version; a record you read late carries the *current* published state.\n * - **410 Gone** means your cursor predates the 90-day retention window. Bootstrap again and\n * **replace** your dataset for the company from the result (records absent from the\n * bootstrap are deleted).\n * - Investor identity fields (`investor.name`, `investor.legal_name`, `investor.email`,\n * `investor.address`, `investor.bio`, `message`, `external_username`) are **omitted**\n * unless the token carries `read:investors:pii`.\n * - Money is integer minor units plus `amounts.currency` (`committed_cents`,\n * `investment_size_cents`, `in_escrow_cents`, `contracts[].override_amount_cents`).\n * `shares` and `average_share_price` are decimal strings, `null` on rounds without shares.\n * `amounts.raised_cents` is the row's contribution to the public raised figure (0 while\n * `needs_whitelisting`); sum it, not `committed_cents`, to match the deal page.\n *\n */\nexport const listCompanyInvestmentChanges = <\n ThrowOnError extends boolean = false,\n>(\n options: Options<ListCompanyInvestmentChangesData, ThrowOnError>,\n): RequestResult<\n ListCompanyInvestmentChangesResponses,\n ListCompanyInvestmentChangesErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n ListCompanyInvestmentChangesResponses,\n ListCompanyInvestmentChangesErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/companies/{company_id}/investments/changes\",\n ...options,\n });\n\n/**\n * Get portfolio summary\n *\n * Returns totals across the authenticated investor's portfolio: cost basis,\n * current value, realized and unrealized gains, and per-status position counts.\n * Accepts the same `status` and `company` filters as `GET /portfolio/positions`\n * to total a slice of the portfolio, such as only exited positions.\n *\n * Requires a user-authorized token. App-only (client credentials) tokens\n * receive 403.\n *\n * Portfolio values are recalculated periodically rather than on each request,\n * so recent investments and valuation changes can take a few minutes to appear.\n * `as_of` is the timestamp of the oldest calculation included in the response.\n *\n * Monetary values are **integer cents**; per-share prices and return multiples\n * are **decimal strings**.\n *\n */\nexport const getPortfolio = <ThrowOnError extends boolean = false>(\n options?: Options<GetPortfolioData, ThrowOnError>,\n): RequestResult<GetPortfolioResponses, GetPortfolioErrors, ThrowOnError> =>\n (options?.client ?? client).get<\n GetPortfolioResponses,\n GetPortfolioErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/portfolio\",\n ...options,\n });\n\n/**\n * List portfolio positions\n *\n * Returns the authenticated investor's positions, one per offering\n * (fundraise), newest first. Position totals cover everything the investor\n * holds in that offering; `securities` breaks the total down by security\n * offering and legal owner, so early bird tiers and personally-held vs\n * entity-held stakes each appear separately. Fund and SPV positions identify\n * the companies the vehicle invested in under `holdings`.\n *\n * To compute an average cost per share, divide `cost_basis_cents` by\n * `shares_held`.\n *\n * Requires a user-authorized token, like `GET /portfolio`.\n *\n */\nexport const listPortfolioPositions = <ThrowOnError extends boolean = false>(\n options?: Options<ListPortfolioPositionsData, ThrowOnError>,\n): RequestResult<\n ListPortfolioPositionsResponses,\n ListPortfolioPositionsErrors,\n ThrowOnError\n> =>\n (options?.client ?? client).get<\n ListPortfolioPositionsResponses,\n ListPortfolioPositionsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/portfolio/positions\",\n ...options,\n });\n\n/**\n * List founder campaigns\n *\n * Retrieves all fundraising campaigns for companies where the authenticated user is a founder.\n * This endpoint returns comprehensive campaign data including funding progress, investor counts,\n * and campaign status.\n *\n * Use this endpoint to:\n * - Build custom founder dashboards\n * - Monitor fundraising progress across multiple campaigns\n * - Generate reports on campaign performance\n * - Integrate campaign data into your own tools\n *\n * Only founders with the appropriate permissions can access this endpoint. The response includes\n * both active and closed campaigns, with detailed metrics for each.\n *\n */\nexport const listCampaigns = <ThrowOnError extends boolean = false>(\n options?: Options<ListCampaignsData, ThrowOnError>,\n): RequestResult<ListCampaignsResponses, ListCampaignsErrors, ThrowOnError> =>\n (options?.client ?? client).get<\n ListCampaignsResponses,\n ListCampaignsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/campaigns\",\n ...options,\n });\n\n/**\n * List syndicates\n *\n * Returns syndicates the authenticated user can manage, based on their roles.\n * Results can be filtered by status and sorted by name or creation date.\n *\n */\nexport const listSyndicates = <ThrowOnError extends boolean = false>(\n options?: Options<ListSyndicatesData, ThrowOnError>,\n): RequestResult<ListSyndicatesResponses, ListSyndicatesErrors, ThrowOnError> =>\n (options?.client ?? client).get<\n ListSyndicatesResponses,\n ListSyndicatesErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates\",\n ...options,\n });\n\n/**\n * Get syndicate details\n *\n * Returns full details for a specific syndicate including settings, team configuration, and summary metrics.\n */\nexport const getSyndicate = <ThrowOnError extends boolean = false>(\n options: Options<GetSyndicateData, ThrowOnError>,\n): RequestResult<GetSyndicateResponses, GetSyndicateErrors, ThrowOnError> =>\n (options.client ?? client).get<\n GetSyndicateResponses,\n GetSyndicateErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}\",\n ...options,\n });\n\n/**\n * Update syndicate settings\n *\n * Update syndicate configuration. Currently supports name, description, and tagline.\n * Requires `write:syndicates` scope and at least operator permission.\n *\n */\nexport const updateSyndicate = <ThrowOnError extends boolean = false>(\n options: Options<UpdateSyndicateData, ThrowOnError>,\n): RequestResult<\n UpdateSyndicateResponses,\n UpdateSyndicateErrors,\n ThrowOnError\n> =>\n (options.client ?? client).patch<\n UpdateSyndicateResponses,\n UpdateSyndicateErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * List members\n *\n * Returns the member directory for a syndicate with role, status, tags, sidebar notes,\n * and investment history summaries. Supports filtering, sorting, search, and pagination.\n *\n */\nexport const listSyndicateMembers = <ThrowOnError extends boolean = false>(\n options: Options<ListSyndicateMembersData, ThrowOnError>,\n): RequestResult<\n ListSyndicateMembersResponses,\n ListSyndicateMembersErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n ListSyndicateMembersResponses,\n ListSyndicateMembersErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members\",\n ...options,\n });\n\n/**\n * Invite member\n *\n * Send an invitation to join the syndicate by email.\n */\nexport const inviteSyndicateMember = <ThrowOnError extends boolean = false>(\n options: Options<InviteSyndicateMemberData, ThrowOnError>,\n): RequestResult<\n InviteSyndicateMemberResponses,\n InviteSyndicateMemberErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n InviteSyndicateMemberResponses,\n InviteSyndicateMemberErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members/invite\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * Remove member (requires intent)\n *\n * Removing a member is irreversible and requires human approval through the Intent system.\n * This endpoint always returns 422 with a `use_intents` error directing you to\n * `POST /intents` with action `syndicates.remove_member`.\n *\n */\nexport const removeSyndicateMember = <ThrowOnError extends boolean = false>(\n options: Options<RemoveSyndicateMemberData, ThrowOnError>,\n): RequestResult<unknown, RemoveSyndicateMemberErrors, ThrowOnError> =>\n (options.client ?? client).delete<\n unknown,\n RemoveSyndicateMemberErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members/{member_id}\",\n ...options,\n });\n\n/**\n * Update member\n *\n * Update title and carry override for a member. Requires operator permission.\n */\nexport const updateSyndicateMember = <ThrowOnError extends boolean = false>(\n options: Options<UpdateSyndicateMemberData, ThrowOnError>,\n): RequestResult<\n UpdateSyndicateMemberResponses,\n UpdateSyndicateMemberErrors,\n ThrowOnError\n> =>\n (options.client ?? client).patch<\n UpdateSyndicateMemberResponses,\n UpdateSyndicateMemberErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members/{member_id}\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * Approve applicant\n *\n * Approve a pending applicant. Only applicants can be approved via API; invitees must accept their invite link.\n */\nexport const approveSyndicateMember = <ThrowOnError extends boolean = false>(\n options: Options<ApproveSyndicateMemberData, ThrowOnError>,\n): RequestResult<\n ApproveSyndicateMemberResponses,\n ApproveSyndicateMemberErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n ApproveSyndicateMemberResponses,\n ApproveSyndicateMemberErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members/{member_id}/approve\",\n ...options,\n });\n\n/**\n * Exile member\n *\n * Exile (hide) a member from the syndicate. Sets their role to exiled.\n */\nexport const hideSyndicateMember = <ThrowOnError extends boolean = false>(\n options: Options<HideSyndicateMemberData, ThrowOnError>,\n): RequestResult<\n HideSyndicateMemberResponses,\n HideSyndicateMemberErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n HideSyndicateMemberResponses,\n HideSyndicateMemberErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members/{member_id}/hide\",\n ...options,\n });\n\n/**\n * Promote member to admin\n *\n * Promote a member to full_access (admin) role. Only the syndicate creator can promote members.\n */\nexport const promoteSyndicateMember = <ThrowOnError extends boolean = false>(\n options: Options<PromoteSyndicateMemberData, ThrowOnError>,\n): RequestResult<\n PromoteSyndicateMemberResponses,\n PromoteSyndicateMemberErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n PromoteSyndicateMemberResponses,\n PromoteSyndicateMemberErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members/{member_id}/promote\",\n ...options,\n });\n\n/**\n * Demote member to operator\n *\n * Demote a member from full_access (admin) to operator permission.\n */\nexport const demoteSyndicateMember = <ThrowOnError extends boolean = false>(\n options: Options<DemoteSyndicateMemberData, ThrowOnError>,\n): RequestResult<\n DemoteSyndicateMemberResponses,\n DemoteSyndicateMemberErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n DemoteSyndicateMemberResponses,\n DemoteSyndicateMemberErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members/{member_id}/demote\",\n ...options,\n });\n\n/**\n * Restore exiled or resigned member\n *\n * Restore a member who was previously exiled or resigned. Sets their role back to member.\n */\nexport const restoreSyndicateMember = <ThrowOnError extends boolean = false>(\n options: Options<RestoreSyndicateMemberData, ThrowOnError>,\n): RequestResult<\n RestoreSyndicateMemberResponses,\n RestoreSyndicateMemberErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n RestoreSyndicateMemberResponses,\n RestoreSyndicateMemberErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members/{member_id}/restore\",\n ...options,\n });\n\n/**\n * Resend invitation\n */\nexport const resendSyndicateInvite = <ThrowOnError extends boolean = false>(\n options: Options<ResendSyndicateInviteData, ThrowOnError>,\n): RequestResult<\n ResendSyndicateInviteResponses,\n ResendSyndicateInviteErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n ResendSyndicateInviteResponses,\n ResendSyndicateInviteErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members/{member_id}/resend_invite\",\n ...options,\n });\n\n/**\n * Reorder members\n *\n * Set the display order for the member directory.\n */\nexport const reorderSyndicateMembers = <ThrowOnError extends boolean = false>(\n options: Options<ReorderSyndicateMembersData, ThrowOnError>,\n): RequestResult<\n ReorderSyndicateMembersResponses,\n ReorderSyndicateMembersErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n ReorderSyndicateMembersResponses,\n ReorderSyndicateMembersErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members/reorder\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * Export members CSV\n *\n * Generate a CSV export of the member directory. Returns the CSV data directly\n * with Content-Type text/csv. Requires operator permission.\n *\n */\nexport const exportSyndicateMembersCsv = <ThrowOnError extends boolean = false>(\n options: Options<ExportSyndicateMembersCsvData, ThrowOnError>,\n): RequestResult<\n ExportSyndicateMembersCsvResponses,\n ExportSyndicateMembersCsvErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n ExportSyndicateMembersCsvResponses,\n ExportSyndicateMembersCsvErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members/export_csv\",\n ...options,\n });\n\n/**\n * List deals\n *\n * Returns the syndicate's **live** deals (open, oversubscribed, or closing) with status,\n * terms, and metrics. Closed and upcoming rounds are not listed; `statistics.total_deals`\n * counts all linked rounds.\n *\n */\nexport const listSyndicateDeals = <ThrowOnError extends boolean = false>(\n options: Options<ListSyndicateDealsData, ThrowOnError>,\n): RequestResult<\n ListSyndicateDealsResponses,\n ListSyndicateDealsErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n ListSyndicateDealsResponses,\n ListSyndicateDealsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/deals\",\n ...options,\n });\n\n/**\n * Get deal details\n *\n * Returns full details for a specific deal including investor breakdown.\n */\nexport const getSyndicateDeal = <ThrowOnError extends boolean = false>(\n options: Options<GetSyndicateDealData, ThrowOnError>,\n): RequestResult<\n GetSyndicateDealResponses,\n GetSyndicateDealErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n GetSyndicateDealResponses,\n GetSyndicateDealErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/deals/{fundraise_id}\",\n ...options,\n });\n\n/**\n * List deal investors\n *\n * Returns syndicate members who invested in this deal. Results are scoped to\n * syndicate member user IDs only and sorted by amount descending.\n *\n * The `user_email` field is **moderator-only** — it returns null for non-moderator\n * callers (i.e., users who are not a manager/operator of the syndicate).\n *\n * `amount` is whole dollars as a string (e.g. `\"5000\"` is $5,000).\n *\n * Offset-paginated: pass `offset` and `per_page`; `meta` carries `total_count`,\n * `offset`, `per_page`, and `has_more`. Without `per_page` the full list is returned.\n *\n */\nexport const listSyndicateDealInvestors = <\n ThrowOnError extends boolean = false,\n>(\n options: Options<ListSyndicateDealInvestorsData, ThrowOnError>,\n): RequestResult<\n ListSyndicateDealInvestorsResponses,\n ListSyndicateDealInvestorsErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n ListSyndicateDealInvestorsResponses,\n ListSyndicateDealInvestorsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/deals/{fundraise_id}/investors\",\n ...options,\n });\n\n/**\n * List member investments\n *\n * Returns this member's investments in syndicate deals. Scoped to the syndicate's\n * selected deals (one per company, matching directory semantics). **Moderator-only.**\n *\n * `amount` and `meta.total_amount` are whole dollars as strings.\n *\n */\nexport const listSyndicateMemberInvestments = <\n ThrowOnError extends boolean = false,\n>(\n options: Options<ListSyndicateMemberInvestmentsData, ThrowOnError>,\n): RequestResult<\n ListSyndicateMemberInvestmentsResponses,\n ListSyndicateMemberInvestmentsErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n ListSyndicateMemberInvestmentsResponses,\n ListSyndicateMemberInvestmentsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members/{member_id}/investments\",\n ...options,\n });\n\n/**\n * Get syndicate statistics\n *\n * Returns aggregate metrics for a syndicate including member counts, deal counts,\n * total raised, and recent activity.\n *\n * `total_raised` and `total_investors` are computed from directory-selected deals\n * (one per company). `total_deals` and `live_deals` use all linked deals.\n *\n * `total_raised` is whole dollars as a string.\n *\n */\nexport const getSyndicateStatistics = <ThrowOnError extends boolean = false>(\n options: Options<GetSyndicateStatisticsData, ThrowOnError>,\n): RequestResult<\n GetSyndicateStatisticsResponses,\n GetSyndicateStatisticsErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n GetSyndicateStatisticsResponses,\n GetSyndicateStatisticsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/statistics\",\n ...options,\n });\n\n/**\n * Get syndicate portfolio summary\n *\n * Returns totals across the syndicate's portfolio: cost basis, current value,\n * gains, per-status deal counts, and the number of distinct investors.\n * Accepts the same `status` and `company` filters as the positions endpoint\n * to total a slice of the portfolio, such as only exited deals.\n *\n * The summary covers the syndicate's funded deals, summed across everyone\n * holding their securities (not just current members), as aggregate figures\n * only. Member-level data is available on the members endpoints.\n *\n * Portfolio values are recalculated periodically rather than on each request,\n * so recent investments and valuation changes can take a few minutes to appear.\n * `as_of` is the timestamp of the oldest calculation included in the response.\n *\n * Monetary values are **integer cents**; per-share prices and return multiples\n * are **decimal strings**.\n *\n */\nexport const getSyndicatePortfolio = <ThrowOnError extends boolean = false>(\n options: Options<GetSyndicatePortfolioData, ThrowOnError>,\n): RequestResult<\n GetSyndicatePortfolioResponses,\n GetSyndicatePortfolioErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n GetSyndicatePortfolioResponses,\n GetSyndicatePortfolioErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/portfolio\",\n ...options,\n });\n\n/**\n * List syndicate portfolio positions\n *\n * Returns the syndicate's portfolio one deal at a time, newest first. Each\n * position is one fundraise (\"offering\"), aggregated across everyone holding\n * its securities, with `investor_count` at both the position and security\n * level.\n *\n * `securities` breaks each position down by security offering (for example,\n * an early bird tier vs the regular terms) — most deals have a single entry.\n * Fund and SPV deals identify the companies the vehicle invested in under\n * `holdings`; some older vehicles have no recorded holdings and return an\n * empty array.\n *\n */\nexport const listSyndicatePortfolioPositions = <\n ThrowOnError extends boolean = false,\n>(\n options: Options<ListSyndicatePortfolioPositionsData, ThrowOnError>,\n): RequestResult<\n ListSyndicatePortfolioPositionsResponses,\n ListSyndicatePortfolioPositionsErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n ListSyndicatePortfolioPositionsResponses,\n ListSyndicatePortfolioPositionsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/portfolio/positions\",\n ...options,\n });\n\n/**\n * Close deal\n *\n * Closing a deal is irreversible and requires human approval through the Intent system.\n * This endpoint server-mints a pending `syndicates.close_deal` intent and returns the deal\n * under `data` plus the intent's `review_url` under `meta.close_deal_intent`. The deal is\n * not transitioned until a permitted human approves the intent in the Wefunder UI.\n * Idempotent: a repeated call returns the same pending intent rather than minting a duplicate.\n *\n */\nexport const closeSyndicateDeal = <ThrowOnError extends boolean = false>(\n options: Options<CloseSyndicateDealData, ThrowOnError>,\n): RequestResult<\n CloseSyndicateDealResponses,\n CloseSyndicateDealErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n CloseSyndicateDealResponses,\n CloseSyndicateDealErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/deals/{fundraise_id}/close\",\n ...options,\n });\n\n/**\n * Finalize deal\n *\n * Finalizing a deal is irreversible and requires human approval through the Intent system.\n * This endpoint server-mints a pending `syndicates.finalize_deal` intent and returns the\n * deal under `data` plus the intent's `review_url` under `meta.finalize_deal_intent`. The\n * finalize runs only when a permitted human approves the intent in the Wefunder UI.\n * Idempotent: a repeated call returns the same pending intent rather than minting a duplicate.\n *\n */\nexport const finalizeSyndicateDeal = <ThrowOnError extends boolean = false>(\n options: Options<FinalizeSyndicateDealData, ThrowOnError>,\n): RequestResult<\n FinalizeSyndicateDealResponses,\n FinalizeSyndicateDealErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n FinalizeSyndicateDealResponses,\n FinalizeSyndicateDealErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/deals/{fundraise_id}/finalize\",\n ...options,\n });\n\n/**\n * Preview an intent without proposing it\n *\n * Runs every check `POST /intents` runs — the action's feature flag, resource type and id,\n * token binding, who may propose, and the handler's own validation — and returns what the\n * reviewer would read, without minting anything. The draft step for agents: admitted by any\n * proposing scope **or** `read:explore`, and the action's own scope is not required, so a user\n * can shape the text before granting the write permission. Same request body as `POST /intents`\n * (without `idempotency_key`). Errors are the same as `POST /intents` would give.\n *\n */\nexport const previewIntent = <ThrowOnError extends boolean = false>(\n options: Options<PreviewIntentData, ThrowOnError>,\n): RequestResult<PreviewIntentResponses, PreviewIntentErrors, ThrowOnError> =>\n (options.client ?? client).post<\n PreviewIntentResponses,\n PreviewIntentErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/intents/preview\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * List intents\n *\n * List intents created by the current token, optionally filtered by status or resource.\n */\nexport const listIntents = <ThrowOnError extends boolean = false>(\n options?: Options<ListIntentsData, ThrowOnError>,\n): RequestResult<ListIntentsResponses, ListIntentsErrors, ThrowOnError> =>\n (options?.client ?? client).get<\n ListIntentsResponses,\n ListIntentsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/intents\",\n ...options,\n });\n\n/**\n * Propose an intent\n *\n * Propose a dangerous or irreversible action for human approval. Returns a `review_url`\n * where a human must review the impact and approve before the action executes.\n *\n * The entity that proposes an intent can never approve it. Approval always happens\n * on Wefunder's UI by a user with permission on the resource.\n *\n * Each action names the scope that may propose it and the resource type it targets\n * (`syndicates.*` → `write:syndicates` on a syndicate; `comments.create` → `write:comments`\n * on a `Company`). The token must hold that action's scope; holding another proposing scope\n * is not enough (403 `insufficient_scope`).\n *\n * `comments.create` posts a question on a company's Ask tab, or an answer to one, as the\n * requesting user once they approve on wefunder.com. `resource_id` is the company (`co_...`);\n * `params` is `{ target_type: \"company\" | \"comment\", target: \"co_...\" | \"cmt_...\", body,\n * disclosure_key? }` (`disclosure_key` ∈ investor, stockholder, promoter, financial_stakeholder).\n * Who may post is the site's own rule: anyone the page is available to may ask (unless the\n * company has closed questions); only the company's team may answer. Only the requester can\n * approve. 20 proposals per user per day (429).\n *\n * An `idempotency_key` names one operation. Reusing it for the same operation returns the\n * existing intent (200) while that intent is pending, approved, executing, or executed;\n * reusing it for a different action, resource, or params is a 409 `idempotency_conflict`.\n *\n * An action still rolling out per account returns 403 `feature_disabled` for a user who is\n * not yet enabled. `POST /intents/preview` runs the same checks without minting.\n *\n * See [Intents documentation](/concepts/intents) for the full pattern.\n *\n */\nexport const createIntent = <ThrowOnError extends boolean = false>(\n options: Options<CreateIntentData, ThrowOnError>,\n): RequestResult<CreateIntentResponses, CreateIntentErrors, ThrowOnError> =>\n (options.client ?? client).post<\n CreateIntentResponses,\n CreateIntentErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/intents\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * Get intent status\n *\n * Check the current status of an intent. Use this to poll for approval\n * after proposing an intent, or subscribe to `intent.*` webhook events instead.\n *\n */\nexport const getIntent = <ThrowOnError extends boolean = false>(\n options: Options<GetIntentData, ThrowOnError>,\n): RequestResult<GetIntentResponses, GetIntentErrors, ThrowOnError> =>\n (options.client ?? client).get<\n GetIntentResponses,\n GetIntentErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/intents/{intent_id}\",\n ...options,\n });\n\n/**\n * List activity events\n *\n * Returns actions taken by OAuth apps authorized by the current user.\n * This is the API backing the user-facing activity feed at Settings > Activity.\n *\n */\nexport const listActivity = <ThrowOnError extends boolean = false>(\n options?: Options<ListActivityData, ThrowOnError>,\n): RequestResult<ListActivityResponses, ListActivityErrors, ThrowOnError> =>\n (options?.client ?? client).get<\n ListActivityResponses,\n ListActivityErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/activity\",\n ...options,\n });\n\n/**\n * List connected apps\n *\n * Returns all OAuth apps the user has authorized, with summary stats.\n */\nexport const listConnectedApps = <ThrowOnError extends boolean = false>(\n options?: Options<ListConnectedAppsData, ThrowOnError>,\n): RequestResult<\n ListConnectedAppsResponses,\n ListConnectedAppsErrors,\n ThrowOnError\n> =>\n (options?.client ?? client).get<\n ListConnectedAppsResponses,\n ListConnectedAppsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/connected-apps\",\n ...options,\n });\n\n/**\n * Revoke connected app\n *\n * Revoke all tokens for this app. Any pending intents from this app are automatically expired.\n *\n */\nexport const revokeConnectedApp = <ThrowOnError extends boolean = false>(\n options: Options<RevokeConnectedAppData, ThrowOnError>,\n): RequestResult<\n RevokeConnectedAppResponses,\n RevokeConnectedAppErrors,\n ThrowOnError\n> =>\n (options.client ?? client).delete<\n RevokeConnectedAppResponses,\n RevokeConnectedAppErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/connected-apps/{app_id}\",\n ...options,\n });\n\n/**\n * Get aggregate attribution statistics\n *\n * Returns aggregate attribution statistics for a campaign. This is a **Tier 0** endpoint\n * available to all OAuth applications with the `read:attribution:aggregate` scope.\n *\n * Use this endpoint to:\n * - Track overall marketing campaign performance\n * - Measure conversion rates by UTM source/campaign\n * - Monitor investment quality metrics\n * - Build performance dashboards\n *\n * The response includes totals and breakdowns by UTM parameters. All counts exclude\n * disputed attributions.\n *\n * **Privacy**: This endpoint returns aggregate data only. No individual investor\n * information is exposed.\n *\n */\nexport const getAttributionStats = <ThrowOnError extends boolean = false>(\n options: Options<GetAttributionStatsData, ThrowOnError>,\n): RequestResult<\n GetAttributionStatsResponses,\n GetAttributionStatsErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n GetAttributionStatsResponses,\n GetAttributionStatsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/campaigns/{campaign_id}/attribution/stats\",\n ...options,\n });\n\n/**\n * List attributed investments\n *\n * Returns a list of attributed investments. The detail level depends on your access:\n *\n * **Tier 1 (Marketing Partners)** - Anonymized data:\n * - Investor identity represented by opaque tokens (not real IDs)\n * - Tokens are campaign-scoped (different token per campaign for same investor)\n * - Investment amounts shown as tiers (small/medium/large), not exact values\n * - No PII (email, name, address) is returned\n *\n * **Tier 2 (Founders/Employees)** - Full data with `detail_level=full`:\n * - Real investment IDs (linkable to Wefunder admin)\n * - Investor name, email, and username\n * - Exact dollar amounts\n *\n * **Access**: Requires Tier 1+ access approval from Wefunder admin.\n *\n */\nexport const listAttributedInvestments = <ThrowOnError extends boolean = false>(\n options: Options<ListAttributedInvestmentsData, ThrowOnError>,\n): RequestResult<\n ListAttributedInvestmentsResponses,\n ListAttributedInvestmentsErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n ListAttributedInvestmentsResponses,\n ListAttributedInvestmentsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/campaigns/{campaign_id}/attribution/investments\",\n ...options,\n });\n\n/**\n * List installations of your app\n *\n * Where the calling application is installed. Someone who manages the app's organization sees\n * every install; anyone else sees the installs they made or could revoke. Revoked installs stay\n * listed for 30 days.\n *\n */\nexport const listInstallations = <ThrowOnError extends boolean = false>(\n options?: Options<ListInstallationsData, ThrowOnError>,\n): RequestResult<\n ListInstallationsResponses,\n ListInstallationsErrors,\n ThrowOnError\n> =>\n (options?.client ?? client).get<\n ListInstallationsResponses,\n ListInstallationsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/installations\",\n ...options,\n });\n\n/**\n * Install your app on a company or syndicate\n *\n * Installs the calling application on a company or syndicate the token's user can edit (or, for a\n * syndicate, manages), and mints the **company-owned token** the install stands for. The token\n * appears in this response only. Requires a token authorized by a user.\n *\n * The install is granted at the caller's tier (founder, admin or editor for a company). An\n * editor-tier install carries read scopes only; write scopes in `scopes` are dropped. Installing\n * on a company outside your own organization requires the app to be approved.\n *\n */\nexport const createInstallation = <ThrowOnError extends boolean = false>(\n options: Options<CreateInstallationData, ThrowOnError>,\n): RequestResult<\n CreateInstallationResponses,\n CreateInstallationErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n CreateInstallationResponses,\n CreateInstallationErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/installations\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * List where you can install your app\n *\n * Companies the token's user can edit and syndicates they manage, with the tier an install would\n * be granted at and the current install if one exists. Requires a token authorized by a user.\n *\n */\nexport const listEligibleInstallTargets = <\n ThrowOnError extends boolean = false,\n>(\n options?: Options<ListEligibleInstallTargetsData, ThrowOnError>,\n): RequestResult<\n ListEligibleInstallTargetsResponses,\n ListEligibleInstallTargetsErrors,\n ThrowOnError\n> =>\n (options?.client ?? client).get<\n ListEligibleInstallTargetsResponses,\n ListEligibleInstallTargetsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/installations/eligible\",\n ...options,\n });\n\n/**\n * Revoke an installation\n *\n * Revokes the install and every token issued for it. Requires a token authorized by a user who\n * can edit the company (or manages the syndicate), or who administers the app's organization.\n *\n */\nexport const revokeInstallation = <ThrowOnError extends boolean = false>(\n options: Options<RevokeInstallationData, ThrowOnError>,\n): RequestResult<\n RevokeInstallationResponses,\n RevokeInstallationErrors,\n ThrowOnError\n> =>\n (options.client ?? client).delete<\n RevokeInstallationResponses,\n RevokeInstallationErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/installations/{external_id}\",\n ...options,\n });\n\n/**\n * Retrieve an installation\n */\nexport const getInstallation = <ThrowOnError extends boolean = false>(\n options: Options<GetInstallationData, ThrowOnError>,\n): RequestResult<\n GetInstallationResponses,\n GetInstallationErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n GetInstallationResponses,\n GetInstallationErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/installations/{external_id}\",\n ...options,\n });\n\n/**\n * Mint a token for an installation\n *\n * Mints another company-owned token for an active install — for example one a founder made through\n * the install link. Scopes default to the install's grant and can only narrow it. The token appears\n * in this response only. Requires a token authorized by a user who installed it, could revoke it,\n * or manages the app's organization.\n *\n */\nexport const createInstallationToken = <ThrowOnError extends boolean = false>(\n options: Options<CreateInstallationTokenData, ThrowOnError>,\n): RequestResult<\n CreateInstallationTokenResponses,\n CreateInstallationTokenErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n CreateInstallationTokenResponses,\n CreateInstallationTokenErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/installations/{external_id}/tokens\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * List webhook endpoints\n *\n * Your application's webhook endpoints. The signing secret is never included. Requires an\n * owner, admin, or developer role in the application's organization.\n *\n */\nexport const listWebhookEndpoints = <ThrowOnError extends boolean = false>(\n options?: Options<ListWebhookEndpointsData, ThrowOnError>,\n): RequestResult<\n ListWebhookEndpointsResponses,\n ListWebhookEndpointsErrors,\n ThrowOnError\n> =>\n (options?.client ?? client).get<\n ListWebhookEndpointsResponses,\n ListWebhookEndpointsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/webhook_endpoints\",\n ...options,\n });\n\n/**\n * Create a webhook endpoint\n *\n * Registers an endpoint for your application. The response is the only time the\n * signing `secret` is returned; store it to verify signatures. Requires an\n * owner, admin, or developer role in the application's organization.\n *\n * On the sandbox API this returns `403 manage_endpoints_on_live_api`: create test\n * endpoints through the live API with `mode: \"test\"`, and they are mirrored into sandbox.\n *\n */\nexport const createWebhookEndpoint = <ThrowOnError extends boolean = false>(\n options: Options<CreateWebhookEndpointData, ThrowOnError>,\n): RequestResult<\n CreateWebhookEndpointResponses,\n CreateWebhookEndpointErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n CreateWebhookEndpointResponses,\n CreateWebhookEndpointErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/webhook_endpoints\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * Remove a webhook endpoint\n *\n * Stops deliveries immediately. The endpoint is retained as removed and cannot be restored.\n * Returns `403 manage_endpoints_on_live_api` on the sandbox API; use the live API.\n *\n */\nexport const deleteWebhookEndpoint = <ThrowOnError extends boolean = false>(\n options: Options<DeleteWebhookEndpointData, ThrowOnError>,\n): RequestResult<\n DeleteWebhookEndpointResponses,\n DeleteWebhookEndpointErrors,\n ThrowOnError\n> =>\n (options.client ?? client).delete<\n DeleteWebhookEndpointResponses,\n DeleteWebhookEndpointErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/webhook_endpoints/{external_id}\",\n ...options,\n });\n\n/**\n * Get a webhook endpoint\n *\n * Requires an owner, admin, or developer role in the application's organization.\n */\nexport const getWebhookEndpoint = <ThrowOnError extends boolean = false>(\n options: Options<GetWebhookEndpointData, ThrowOnError>,\n): RequestResult<\n GetWebhookEndpointResponses,\n GetWebhookEndpointErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n GetWebhookEndpointResponses,\n GetWebhookEndpointErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/webhook_endpoints/{external_id}\",\n ...options,\n });\n\n/**\n * Update a webhook endpoint\n *\n * `events` replaces the subscription list wholesale (no merge); omit it to leave it\n * unchanged. An endpoint must subscribe to at least one event, so `[]` and `null` are\n * rejected; delete the endpoint to stop all deliveries. Requires an org management role.\n * Returns `403 manage_endpoints_on_live_api` on the sandbox API; use the live API.\n *\n */\nexport const updateWebhookEndpoint = <ThrowOnError extends boolean = false>(\n options: Options<UpdateWebhookEndpointData, ThrowOnError>,\n): RequestResult<\n UpdateWebhookEndpointResponses,\n UpdateWebhookEndpointErrors,\n ThrowOnError\n> =>\n (options.client ?? client).patch<\n UpdateWebhookEndpointResponses,\n UpdateWebhookEndpointErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/webhook_endpoints/{external_id}\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * Rotate the signing secret\n *\n * Returns a new signing secret (shown once). The previous secret keeps signing for a\n * 24h overlap window, so deliveries carry a `v1` for both; verify against either.\n * Returns `403 manage_endpoints_on_live_api` on the sandbox API; use the live API.\n *\n */\nexport const rotateWebhookEndpointSecret = <\n ThrowOnError extends boolean = false,\n>(\n options: Options<RotateWebhookEndpointSecretData, ThrowOnError>,\n): RequestResult<\n RotateWebhookEndpointSecretResponses,\n RotateWebhookEndpointSecretErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n RotateWebhookEndpointSecretResponses,\n RotateWebhookEndpointSecretErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/webhook_endpoints/{external_id}/rotate_secret\",\n ...options,\n });\n\n/**\n * Re-enable a disabled endpoint\n *\n * Recovery after auto-disable. Idempotent. Requires an org management role on the live API.\n * Also allowed on the sandbox API for an endpoint sandbox itself disabled (sandbox runs its own\n * health checks on its mirror of a test endpoint), authorized by the caller's realm.\n *\n */\nexport const reenableWebhookEndpoint = <ThrowOnError extends boolean = false>(\n options: Options<ReenableWebhookEndpointData, ThrowOnError>,\n): RequestResult<\n ReenableWebhookEndpointResponses,\n ReenableWebhookEndpointErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n ReenableWebhookEndpointResponses,\n ReenableWebhookEndpointErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/webhook_endpoints/{external_id}/reenable\",\n ...options,\n });\n\n/**\n * Send a test event\n *\n * Sends a real, signed example event (fake values) using the production envelope,\n * signature scheme, and transport, and reports the outcome inline. Does not affect\n * delivery health. Rate-limited to 10 per minute per endpoint. Investor email appears\n * in the example only if your application holds `read:investors:pii`, matching what\n * real deliveries can carry.\n *\n */\nexport const testWebhookEndpoint = <ThrowOnError extends boolean = false>(\n options: Options<TestWebhookEndpointData, ThrowOnError>,\n): RequestResult<\n TestWebhookEndpointResponses,\n TestWebhookEndpointErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n TestWebhookEndpointResponses,\n TestWebhookEndpointErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/webhook_endpoints/{external_id}/test\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * List attribution webhook subscriptions\n *\n * Returns all active webhook subscriptions for this campaign belonging to\n * your OAuth application.\n *\n * **Tier 1** endpoint requiring admin-approved access with the\n * `read:attribution:anonymized` scope.\n *\n */\nexport const listWebhookSubscriptions = <ThrowOnError extends boolean = false>(\n options: Options<ListWebhookSubscriptionsData, ThrowOnError>,\n): RequestResult<\n ListWebhookSubscriptionsResponses,\n ListWebhookSubscriptionsErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n ListWebhookSubscriptionsResponses,\n ListWebhookSubscriptionsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/campaigns/{campaign_id}/attribution/webhooks\",\n ...options,\n });\n\n/**\n * Create webhook subscription\n *\n * Creates a new webhook subscription for this campaign. When attributed\n * investments change state, we'll POST a JSON payload to your target URL.\n *\n * **Tier 1** endpoint requiring admin-approved access.\n *\n * ## Webhook Payload\n *\n * Payloads include anonymized data (tokens, amount tiers) matching the\n * `/attribution/investments` endpoint.\n *\n * ## Security\n *\n * - `target_url` must use HTTPS\n * - `target_url` cannot resolve to private/internal IPs (SSRF protection)\n * - Payloads are signed with HMAC-SHA256 using the returned `secret`\n *\n * ## Verification\n *\n * Verify webhook signatures using the `X-Wefunder-Signature` header:\n * ```\n * timestamp = headers['X-Wefunder-Timestamp']\n * signature = headers['X-Wefunder-Signature']\n * expected = \"sha256=\" + HMAC-SHA256(secret, timestamp + \".\" + raw_body)\n * ```\n *\n * Reject requests where:\n * - Signature doesn't match\n * - Timestamp is more than 5 minutes old (replay protection)\n *\n */\nexport const createWebhookSubscription = <ThrowOnError extends boolean = false>(\n options: Options<CreateWebhookSubscriptionData, ThrowOnError>,\n): RequestResult<\n CreateWebhookSubscriptionResponses,\n CreateWebhookSubscriptionErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n CreateWebhookSubscriptionResponses,\n CreateWebhookSubscriptionErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/campaigns/{campaign_id}/attribution/webhooks\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * Delete webhook subscription\n *\n * Deactivates a webhook subscription. The subscription will stop receiving\n * events but historical delivery data is retained for 7 days.\n *\n */\nexport const deleteWebhookSubscription = <ThrowOnError extends boolean = false>(\n options: Options<DeleteWebhookSubscriptionData, ThrowOnError>,\n): RequestResult<\n DeleteWebhookSubscriptionResponses,\n DeleteWebhookSubscriptionErrors,\n ThrowOnError\n> =>\n (options.client ?? client).delete<\n DeleteWebhookSubscriptionResponses,\n DeleteWebhookSubscriptionErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/campaigns/{campaign_id}/attribution/webhooks/{webhook_id}\",\n ...options,\n });\n\n/**\n * Get webhook subscription details\n *\n * Returns details for a specific webhook subscription including recent\n * delivery history.\n *\n */\nexport const getWebhookSubscription = <ThrowOnError extends boolean = false>(\n options: Options<GetWebhookSubscriptionData, ThrowOnError>,\n): RequestResult<\n GetWebhookSubscriptionResponses,\n GetWebhookSubscriptionErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n GetWebhookSubscriptionResponses,\n GetWebhookSubscriptionErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/campaigns/{campaign_id}/attribution/webhooks/{webhook_id}\",\n ...options,\n });\n\n/**\n * Send test webhook\n *\n * Sends a test webhook to verify your endpoint is working correctly.\n * The test payload includes a `\"event\": \"test\"` field to distinguish\n * it from real events.\n *\n */\nexport const testWebhookSubscription = <ThrowOnError extends boolean = false>(\n options: Options<TestWebhookSubscriptionData, ThrowOnError>,\n): RequestResult<\n TestWebhookSubscriptionResponses,\n TestWebhookSubscriptionErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n TestWebhookSubscriptionResponses,\n TestWebhookSubscriptionErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/campaigns/{campaign_id}/attribution/webhooks/{webhook_id}/test\",\n ...options,\n });\n\n/**\n * Regenerate webhook signing secret\n *\n * Generates a new HMAC signing secret for the webhook subscription.\n * The old secret is immediately invalidated.\n *\n * **Important**: Store the new secret securely - it cannot be retrieved later.\n *\n */\nexport const regenerateWebhookSecret = <ThrowOnError extends boolean = false>(\n options: Options<RegenerateWebhookSecretData, ThrowOnError>,\n): RequestResult<\n RegenerateWebhookSecretResponses,\n RegenerateWebhookSecretErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n RegenerateWebhookSecretResponses,\n RegenerateWebhookSecretErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/campaigns/{campaign_id}/attribution/webhooks/{webhook_id}/regenerate_secret\",\n ...options,\n });\n\n/**\n * Reactivate disabled webhook\n *\n * Reactivates a webhook subscription that was auto-disabled after\n * consecutive failures. Resets the failure counter to 0.\n *\n * Use this after fixing issues with your webhook endpoint.\n *\n */\nexport const reactivateWebhookSubscription = <\n ThrowOnError extends boolean = false,\n>(\n options: Options<ReactivateWebhookSubscriptionData, ThrowOnError>,\n): RequestResult<\n ReactivateWebhookSubscriptionResponses,\n ReactivateWebhookSubscriptionErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n ReactivateWebhookSubscriptionResponses,\n ReactivateWebhookSubscriptionErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/campaigns/{campaign_id}/attribution/webhooks/{webhook_id}/reactivate\",\n ...options,\n });\n\n/**\n * Get current user's attribution profile\n *\n * Returns the authenticated user's marketing partner profile and connected campaigns.\n * If the user is not registered as a marketing partner, returns partner info as null.\n *\n */\nexport const getAttributionMe = <ThrowOnError extends boolean = false>(\n options?: Options<GetAttributionMeData, ThrowOnError>,\n): RequestResult<\n GetAttributionMeResponses,\n GetAttributionMeErrors,\n ThrowOnError\n> =>\n (options?.client ?? client).get<\n GetAttributionMeResponses,\n GetAttributionMeErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/attribution/me\",\n ...options,\n });\n\n/**\n * List campaigns accessible to the current user\n *\n * Returns all campaigns the authenticated user can access for attribution data.\n * For founders, this includes their own campaigns.\n * For marketing partners, this includes campaigns they've been granted access to.\n *\n */\nexport const listAttributionCampaigns = <ThrowOnError extends boolean = false>(\n options?: Options<ListAttributionCampaignsData, ThrowOnError>,\n): RequestResult<\n ListAttributionCampaignsResponses,\n ListAttributionCampaignsErrors,\n ThrowOnError\n> =>\n (options?.client ?? client).get<\n ListAttributionCampaignsResponses,\n ListAttributionCampaignsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/attribution/campaigns\",\n ...options,\n });\n\n/**\n * Register as a marketing partner\n *\n * Registers the authenticated user as a marketing partner.\n * After registration, the partner can create invites to request access to campaigns.\n *\n */\nexport const registerAsPartner = <ThrowOnError extends boolean = false>(\n options: Options<RegisterAsPartnerData, ThrowOnError>,\n): RequestResult<\n RegisterAsPartnerResponses,\n RegisterAsPartnerErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n RegisterAsPartnerResponses,\n RegisterAsPartnerErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/attribution/partners/register\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * List partner invites\n *\n * Returns all invites created by or sent to the authenticated user.\n * Includes both pending and accepted invites.\n *\n */\nexport const listPartnerInvites = <ThrowOnError extends boolean = false>(\n options?: Options<ListPartnerInvitesData, ThrowOnError>,\n): RequestResult<\n ListPartnerInvitesResponses,\n ListPartnerInvitesErrors,\n ThrowOnError\n> =>\n (options?.client ?? client).get<\n ListPartnerInvitesResponses,\n ListPartnerInvitesErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/attribution/invites\",\n ...options,\n });\n\n/**\n * Create a partner invite\n *\n * Creates an invite to establish a partner-company connection.\n *\n * **Directions**:\n * - `partner_to_founder`: Marketing partner invites a founder to grant access\n * - `founder_to_partner`: Founder invites a marketing partner to access their campaign\n *\n * For `partner_to_founder`: Creates a shareable invite link.\n * For `founder_to_partner`: Sends an email to the partner.\n *\n */\nexport const createPartnerInvite = <ThrowOnError extends boolean = false>(\n options: Options<CreatePartnerInviteData, ThrowOnError>,\n): RequestResult<\n CreatePartnerInviteResponses,\n CreatePartnerInviteErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n CreatePartnerInviteResponses,\n CreatePartnerInviteErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/attribution/invites\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * Revoke a partner invite\n *\n * Revokes a pending invite. Only the creator can revoke an invite.\n * Accepted invites cannot be revoked (delete the connection instead).\n *\n */\nexport const revokePartnerInvite = <ThrowOnError extends boolean = false>(\n options: Options<RevokePartnerInviteData, ThrowOnError>,\n): RequestResult<\n RevokePartnerInviteResponses,\n RevokePartnerInviteErrors,\n ThrowOnError\n> =>\n (options.client ?? client).delete<\n RevokePartnerInviteResponses,\n RevokePartnerInviteErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/attribution/invites/{token}\",\n ...options,\n });\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport {\n type Client,\n type ClientOptions,\n type Config,\n createClient,\n createConfig,\n} from \"./client\";\nimport type { ClientOptions as ClientOptions2 } from \"./types.gen\";\n\n/**\n * The `createClientConfig()` function will be called on client initialization\n * and the returned object will become the client's initial configuration.\n *\n * You may want to initialize your client this way instead of calling\n * `setConfig()`. This is useful for example if you're using Next.js\n * to ensure your client always has the correct values.\n */\nexport type CreateClientConfig<T extends ClientOptions = ClientOptions2> = (\n override?: Config<ClientOptions & T>,\n) => Config<Required<ClientOptions> & T>;\n\nexport const client: Client = createClient(\n createConfig<ClientOptions2>({ baseUrl: \"https://api.wefunder.com\" }),\n);\n","// The Wefunder client — the stable, hand-written public surface over the generated\n// layer. Wires: single API base (the edge proxy routes live/sandbox by token prefix,\n// so we do NOT route by prefix — plan §4.2 #1), a pinned Wefunder-Version, the\n// retry/refresh fetch wrapper, token rotation, typed-error unwrapping, and lazy\n// auto-pagination. Resource namespaces cover the common GA paths; `raw` exposes\n// every generated operation, pre-bound, as an escape hatch.\n\nimport { createClient, type Client } from \"./generated/client/index.js\";\nimport { createFetch, type RetryOptions } from \"./http.js\";\nimport { TokenManager, type TokenStore } from \"./token-manager.js\";\nimport { WefunderError, requestIdFrom } from \"./errors.js\";\nimport { clientCredentialsGrant, type TokenSet, type OAuthHostOptions } from \"./oauth.js\";\nimport { paginate, collect, type Cursor, type Page } from \"./pagination.js\";\nimport * as ops from \"./generated/sdk.gen.js\";\nimport type {\n User,\n InvestmentDeltaRecord,\n Offering,\n Campaign,\n Syndicate,\n Intent,\n AttributionMe,\n PortfolioPosition,\n PortfolioSummaryEnvelope,\n ListOfferingsData,\n ListIntentsData,\n ListInvestmentsData,\n GetPortfolioData,\n ListPortfolioPositionsData,\n WebhookEndpoint,\n WebhookEndpointListEnvelope,\n WebhookEndpointTestResultEnvelope,\n CreateWebhookEndpointData,\n UpdateWebhookEndpointData,\n DeleteWebhookEndpointResponses,\n} from \"./generated/types.gen.js\";\nimport type { WebhookEventName } from \"./webhooks.js\";\n\n/** Body for `wf.webhookEndpoints.create()`. */\nexport type CreateWebhookEndpointInput = CreateWebhookEndpointData[\"body\"];\n/** Body for `wf.webhookEndpoints.update()` — `events` replaces the list wholesale. */\nexport type UpdateWebhookEndpointInput = NonNullable<UpdateWebhookEndpointData[\"body\"]>;\n/** The list envelope, with `meta.quota` (max endpoints per app). */\nexport type WebhookEndpointList = WebhookEndpointListEnvelope;\n/** Outcome of `wf.webhookEndpoints.test()`. */\nexport type WebhookTestOutcome = NonNullable<WebhookEndpointTestResultEnvelope[\"data\"]>;\n/** Outcome of `wf.webhookEndpoints.remove()`. */\nexport type WebhookEndpointRemoved = NonNullable<DeleteWebhookEndpointResponses[200][\"data\"]>;\n\n/** Documented `sort` values for the offerings list, from the generated op. */\nexport type OfferingSort = NonNullable<ListOfferingsData[\"query\"]>[\"sort\"];\n/**\n * An investment record as `GET /investments` and `GET /investments/{id}` return it\n * (the Investment Delta shape — a full record or, for company audiences, a tombstone\n * with `visible: false`).\n */\nexport type Investment = InvestmentDeltaRecord;\n/** Filters + sync controls for `GET /investments` (`cursor` is managed by auto-pagination). */\nexport type InvestmentsQuery = NonNullable<ListInvestmentsData[\"query\"]>;\nexport type InvestmentsFilters = Omit<InvestmentsQuery, \"cursor\">;\n/** Documented `status` filter values for the intents list, from the generated op. */\nexport type IntentStatus = NonNullable<ListIntentsData[\"query\"]>[\"status\"];\n/** Portfolio summary filters shared with the positions endpoint. */\nexport type PortfolioFilters = NonNullable<GetPortfolioData[\"query\"]>;\n/** Portfolio status values documented by the API. */\nexport type PortfolioStatus = NonNullable<PortfolioFilters[\"status\"]>;\n/** Filters and pagination controls for portfolio positions. */\nexport type PortfolioPositionsQuery = NonNullable<ListPortfolioPositionsData[\"query\"]>;\n/** Portfolio position filters, excluding the cursor managed by auto-pagination. */\nexport type PortfolioPositionsFilters = Omit<PortfolioPositionsQuery, \"cursor\">;\n/** The summary resource inside the API's data envelope. */\nexport type PortfolioSummary = NonNullable<PortfolioSummaryEnvelope[\"data\"]>;\n\n// Version-free base — the edge gateway serves the API at the host root; `/api/v2`\n// remains a working back-compat alias. The API version is pinned via the\n// `Wefunder-Version` header (DEFAULT_API_VERSION), not the path.\nexport const DEFAULT_API_BASE_URL = \"https://api.wefunder.com\";\nexport const DEFAULT_API_VERSION = \"2025-01-15\";\n\nexport type Mode = \"live\" | \"test\" | \"unknown\";\n\nexport function modeForToken(token: string): Mode {\n if (token.startsWith(\"at_live_\")) return \"live\";\n if (token.startsWith(\"at_test_\")) return \"test\";\n return \"unknown\";\n}\n\nexport interface WefunderOptions extends OAuthHostOptions {\n /** A bearer access token. Either this or `tokens` is required. */\n accessToken?: string;\n /** A full token set (access + rotating refresh). Enables auto-refresh. */\n tokens?: TokenSet;\n /** Needed (with the refresh token) to auto-refresh on expiry/401. */\n clientId?: string;\n clientSecret?: string;\n /**\n * Marks this as a client_credentials client so the SDK auto-re-mints on expiry/401\n * (cc tokens have no refresh token). `fromClientCredentials` sets this for you.\n */\n clientCredentials?: { scopes?: string[] };\n apiVersion?: string;\n /** Override the API base. The edge proxy routes mode by token prefix — leave default in prod. */\n baseUrl?: string;\n // OAuth hosts (oauthBaseUrl / authorizeBaseUrl / tokenBaseUrl) come from OAuthHostOptions.\n store?: TokenStore;\n onTokenRefresh?: (tokens: TokenSet) => void | Promise<void>;\n retry?: RetryOptions;\n // --- injectables (testing) ---\n fetch?: typeof fetch;\n now?: () => number;\n sleep?: (ms: number) => Promise<void>;\n random?: () => number;\n}\n\ntype Result<T> = Promise<{ data?: T; error?: unknown; response?: Response }>;\n\n/** Every generated operation, pre-bound to this client. */\ntype RawOps = {\n [K in keyof typeof ops]: (typeof ops)[K] extends (o: infer O) => infer R\n ? (options?: Omit<O & object, \"client\">) => R\n : never;\n};\n\nexport class Wefunder {\n readonly mode: Mode;\n readonly raw: RawOps;\n #client: Client;\n #tokens: TokenManager;\n\n constructor(opts: WefunderOptions) {\n const tokenSet: TokenSet | undefined =\n opts.tokens ?? (opts.accessToken ? { accessToken: opts.accessToken } : undefined);\n if (!tokenSet) {\n throw new Error(\"Wefunder: provide `accessToken` or `tokens`.\");\n }\n this.mode = modeForToken(tokenSet.accessToken);\n\n // For client_credentials clients, build a re-mint closure from the stored grant\n // inputs so the TokenManager can recover expired tokens (which have no refresh token).\n const reMint =\n opts.clientCredentials && opts.clientId && opts.clientSecret\n ? () =>\n clientCredentialsGrant({\n clientId: opts.clientId!,\n clientSecret: opts.clientSecret!,\n scopes: opts.clientCredentials!.scopes,\n oauthBaseUrl: opts.oauthBaseUrl,\n tokenBaseUrl: opts.tokenBaseUrl,\n fetch: opts.fetch,\n now: opts.now,\n })\n : undefined;\n\n this.#tokens = new TokenManager({\n tokens: tokenSet,\n clientId: opts.clientId,\n clientSecret: opts.clientSecret,\n reMint,\n oauthBaseUrl: opts.oauthBaseUrl,\n tokenBaseUrl: opts.tokenBaseUrl,\n onTokenRefresh: opts.onTokenRefresh,\n store: opts.store,\n fetch: opts.fetch,\n now: opts.now,\n });\n\n const wrappedFetch = createFetch({\n tokenManager: this.#tokens,\n fetch: opts.fetch,\n now: opts.now,\n sleep: opts.sleep,\n random: opts.random,\n retry: opts.retry,\n });\n\n this.#client = createClient({\n baseUrl: opts.baseUrl ?? DEFAULT_API_BASE_URL,\n headers: { \"Wefunder-Version\": opts.apiVersion ?? DEFAULT_API_VERSION },\n auth: () => this.#tokens.getAccessToken(),\n fetch: wrappedFetch,\n });\n\n this.raw = this.#buildRaw();\n }\n\n /** Server-to-server: exchange client credentials for a token, then build a client. */\n static async fromClientCredentials(\n opts: OAuthHostOptions & {\n clientId: string;\n clientSecret: string;\n scopes?: string[];\n apiVersion?: string;\n baseUrl?: string;\n fetch?: typeof fetch;\n now?: () => number;\n },\n ): Promise<Wefunder> {\n const tokens = await clientCredentialsGrant({\n clientId: opts.clientId,\n clientSecret: opts.clientSecret,\n scopes: opts.scopes,\n oauthBaseUrl: opts.oauthBaseUrl,\n tokenBaseUrl: opts.tokenBaseUrl,\n fetch: opts.fetch,\n now: opts.now,\n });\n return new Wefunder({\n tokens,\n clientId: opts.clientId,\n clientSecret: opts.clientSecret,\n clientCredentials: { scopes: opts.scopes }, // enables auto-re-mint on expiry/401\n oauthBaseUrl: opts.oauthBaseUrl,\n tokenBaseUrl: opts.tokenBaseUrl,\n apiVersion: opts.apiVersion,\n baseUrl: opts.baseUrl,\n fetch: opts.fetch,\n now: opts.now,\n });\n }\n\n /** The live token set (e.g. to persist after construction). */\n get tokens(): TokenSet {\n return this.#tokens.current;\n }\n\n // ---- unwrap: turn the {data,error,response} result into data-or-throw ----\n async #unwrap<T>(p: Result<T>): Promise<T> {\n const { data, error, response } = await p;\n if (response && response.ok && error === undefined) return data as T;\n const status = response?.status ?? 0;\n // The runtime error envelope nests request_id + remediation UNDER `error`\n // (api/v2/base_controller.rb#render_error), even though the spec's Error\n // schema models neither. Read them from there; fall back to top-level.\n const env = (error ?? {}) as {\n error?: { type?: string; message?: string; details?: unknown; request_id?: string; remediation?: string };\n request_id?: string;\n };\n throw new WefunderError({\n status,\n type: env.error?.type ?? \"api_error\",\n message: env.error?.message ?? response?.statusText ?? \"Request failed\",\n // X-Wf-Request-Id header is primary (present even on non-JSON edge errors).\n requestId: requestIdFrom(response, env.error?.request_id ?? env.request_id),\n details: env.error?.details,\n remediation: env.error?.remediation,\n });\n }\n\n // Single-resource ops return a `{ data: Entity }` envelope; strip it for ergonomics.\n async #unwrapData<T>(p: Result<unknown>): Promise<T> {\n const env = await this.#unwrap<{ data?: T }>(p as Result<{ data?: T }>);\n return env.data as T;\n }\n\n #buildRaw(): RawOps {\n const raw = {} as Record<string, unknown>;\n for (const [name, fn] of Object.entries(ops)) {\n raw[name] = (options?: Record<string, unknown>) =>\n (fn as (o: unknown) => unknown)({ ...options, client: this.#client });\n }\n return raw as RawOps;\n }\n\n /**\n * Unwrap any generated op result (incl. `wf.raw.*`) the way the ergonomic\n * namespaces do: returns the response body on success, throws a typed\n * `WefunderError` (with `request_id`) on failure. Lets `raw` callers keep the\n * SDK's error handling. (Stress-test finding C.)\n */\n unwrap<T>(p: Result<T>): Promise<T> {\n return this.#unwrap(p);\n }\n\n // Generic page helper: forwards the endpoint's full query (cursor + documented\n // params like `sort`), not just the cursor. (Stress-test finding B.)\n #page<T, Q extends { cursor?: Cursor } = { cursor?: Cursor }>(\n fn: (o: { client: Client; query?: Q }) => Result<Page<T>>,\n ) {\n return (query?: Q): Promise<Page<T>> =>\n this.#unwrap(fn({ client: this.#client, query }) as Result<Page<T>>);\n }\n\n // ---- resource namespaces (common GA paths) ----\n\n users = {\n me: () => this.#unwrapData<User>(ops.getCurrentUser({ client: this.#client })),\n };\n\n offerings = {\n list: this.#page<Offering, { cursor?: Cursor; sort?: OfferingSort }>(ops.listOfferings as never),\n all: (query?: { sort?: OfferingSort }): AsyncGenerator<Offering> =>\n paginate((cursor) => this.offerings.list({ ...query, cursor })),\n collect: (query?: { sort?: OfferingSort }): Promise<Offering[]> =>\n collect((cursor) => this.offerings.list({ ...query, cursor })),\n get: (externalId: string) =>\n this.#unwrapData<Offering>(\n ops.getOffering({ client: this.#client, path: { external_id: externalId } }),\n ),\n };\n\n /**\n * Investments (`read:investments`). `list` is a bootstrap listing; pass `updated_since`\n * or a saved `cursor` for sync mode (`meta.mode === \"delta\"`). Persist `meta.next_cursor`\n * from your last page — it is always present — and resume from it next time.\n */\n investments = {\n list: this.#page<Investment, InvestmentsQuery>(ops.listInvestments as never),\n all: (query?: InvestmentsFilters): AsyncGenerator<Investment> =>\n paginate((cursor) => this.investments.list({ ...query, cursor: cursor as string | undefined })),\n collect: (query?: InvestmentsFilters): Promise<Investment[]> =>\n collect((cursor) => this.investments.list({ ...query, cursor: cursor as string | undefined })),\n /** The current record (not the published projection) for one investment (`inv_…`). */\n get: (id: string) =>\n this.#unwrapData<Investment>(ops.getInvestment({ client: this.#client, path: { id } })),\n };\n\n portfolio = {\n get: (query?: PortfolioFilters) =>\n this.#unwrapData<PortfolioSummary>(ops.getPortfolio({ client: this.#client, query })),\n positions: {\n list: this.#page<PortfolioPosition, PortfolioPositionsQuery>(\n ops.listPortfolioPositions as never,\n ),\n all: (query?: PortfolioPositionsFilters): AsyncGenerator<PortfolioPosition> =>\n paginate((cursor) => this.portfolio.positions.list({ ...query, cursor: cursor as number })),\n collect: (query?: PortfolioPositionsFilters): Promise<PortfolioPosition[]> =>\n collect((cursor) => this.portfolio.positions.list({ ...query, cursor: cursor as number })),\n },\n };\n\n campaigns = {\n list: this.#page<Campaign>(ops.listCampaigns as never),\n all: (): AsyncGenerator<Campaign> => paginate((cursor) => this.campaigns.list({ cursor })),\n collect: (): Promise<Campaign[]> => collect((cursor) => this.campaigns.list({ cursor })),\n };\n\n syndicates = {\n list: this.#page<Syndicate, { cursor?: Cursor; limit?: number }>(ops.listSyndicates as never),\n all: (query?: { limit?: number }): AsyncGenerator<Syndicate> =>\n paginate((cursor) => this.syndicates.list({ ...query, cursor })),\n get: (id: number | string) =>\n this.#unwrapData<Syndicate>(ops.getSyndicate({ client: this.#client, path: { id } as never })),\n };\n\n intents = {\n list: this.#page<\n Intent,\n { cursor?: Cursor; status?: IntentStatus; resource_type?: string; resource_id?: number; limit?: number }\n >(ops.listIntents as never),\n all: (query?: {\n status?: IntentStatus;\n resource_type?: string;\n resource_id?: number;\n limit?: number;\n }): AsyncGenerator<Intent> => paginate((cursor) => this.intents.list({ ...query, cursor })),\n get: (id: number | string) =>\n this.#unwrapData<Intent>(ops.getIntent({ client: this.#client, path: { id } as never })),\n };\n\n attribution = {\n me: () => this.#unwrapData<AttributionMe>(ops.getAttributionMe({ client: this.#client })),\n };\n\n /**\n * Webhook endpoints (`/webhook_endpoints`, scopes `read:webhooks` / `write:webhooks`).\n * Endpoints belong to your application and are managed through the LIVE API —\n * create sandbox receivers there with `mode: \"test\"`; they're mirrored into\n * sandbox. The signing `secret` is returned ONLY by `create` and `rotateSecret`.\n * Verify deliveries with `constructEvent` (see the webhooks module).\n */\n webhookEndpoints = {\n /** All of your app's endpoints (secret omitted). `meta.quota` is the per-app limit. */\n list: (): Promise<WebhookEndpointList> =>\n this.#unwrap<WebhookEndpointList>(ops.listWebhookEndpoints({ client: this.#client })),\n get: (id: string) =>\n this.#unwrapData<WebhookEndpoint>(\n ops.getWebhookEndpoint({ client: this.#client, path: { external_id: id } }),\n ),\n /** Store `attributes.secret` from the result — it is never shown again. */\n create: (input: CreateWebhookEndpointInput) =>\n this.#unwrapData<WebhookEndpoint>(ops.createWebhookEndpoint({ client: this.#client, body: input })),\n /** `events` replaces the subscription list wholesale (no merge); omit to leave unchanged. */\n update: (id: string, input: UpdateWebhookEndpointInput) =>\n this.#unwrapData<WebhookEndpoint>(\n ops.updateWebhookEndpoint({ client: this.#client, path: { external_id: id }, body: input }),\n ),\n /** Stops deliveries immediately. Removal is permanent — create a new endpoint to resume. */\n remove: (id: string) =>\n this.#unwrapData<WebhookEndpointRemoved>(\n ops.deleteWebhookEndpoint({ client: this.#client, path: { external_id: id } }),\n ),\n /**\n * New secret (shown once). The old one keeps signing for a 24h overlap — deliveries\n * carry a `v1` for both, and `constructEvent` accepts either.\n */\n rotateSecret: (id: string) =>\n this.#unwrapData<WebhookEndpoint>(\n ops.rotateWebhookEndpointSecret({ client: this.#client, path: { external_id: id } }),\n ),\n /** Recover an auto-disabled endpoint after fixing your server. Idempotent. */\n reenable: (id: string) =>\n this.#unwrapData<WebhookEndpoint>(\n ops.reenableWebhookEndpoint({ client: this.#client, path: { external_id: id } }),\n ),\n /**\n * POST a real, signed example event at the endpoint (production envelope + signature)\n * and report the outcome inline. Defaults to the endpoint's first subscribed event.\n * Doesn't affect delivery health. Rate-limited to 10/min per endpoint.\n */\n test: (id: string, event?: WebhookEventName) =>\n this.#unwrapData<WebhookTestOutcome>(\n ops.testWebhookEndpoint({\n client: this.#client,\n path: { external_id: id },\n body: event ? { event } : undefined,\n }),\n ),\n };\n}\n","// Webhook verification + parsing for Wefunder platform events.\n//\n// The shipped scheme (docs.wefunder.com → Partner API → Webhooks → Verification;\n// app/models/webhook_endpoint.rb#signature_header) is a single Stripe-style header:\n//\n// Wefunder-Signature: t=<unix seconds>,v1=<hex>[,v1=<hex>]\n// v1 = HMAC-SHA256(secret, \"<t>.<raw_body>\")\n//\n// During a secret rotation the header carries one `v1` per active secret (24h\n// overlap); a delivery is valid if ANY `v1` matches. Consumers enforce a replay\n// tolerance on `t` (documented: 5 minutes). Every delivery body is the envelope\n// `{ id: \"evt_…\", event, created_at, mode, data }` — `id` is the dedup key.\n//\n// The retired attribution surface (`/campaigns/:id/attribution/webhooks`) signed\n// differently (`X-Wefunder-Signature: sha256=<hex>` + `X-Wefunder-Timestamp`).\n// `constructEvent` still accepts that shape so an attribution subscriber isn't\n// stranded, but everything new should target the platform-events scheme.\n\nimport { createHmac, timingSafeEqual } from \"node:crypto\";\nimport type { CreateWebhookEndpointData } from \"./generated/types.gen.js\";\n\n// ---------------------------------------------------------------------------\n// Event names + payload types\n// ---------------------------------------------------------------------------\n\n/**\n * Every event name in the catalog, derived from the spec's `events` enum on\n * `POST /webhook_endpoints` so it can't drift from the API.\n */\nexport type WebhookEventName = CreateWebhookEndpointData[\"body\"][\"events\"][number];\n\n/** Delivery mode — `test` for sandbox facts, `live` otherwise. */\nexport type WebhookMode = \"live\" | \"test\";\n\n/** A person reference on a payload: partner-visible id + name, never email. */\nexport interface WebhookPersonRef {\n id: string | null;\n name: string | null;\n}\n\n/** The investor on an `investment.*` event. `email` needs `read:investors:pii`. */\nexport interface WebhookInvestor {\n id: string | null;\n name?: string | null;\n email?: string | null;\n}\n\n/**\n * The investor across all of the company's offerings in the same raise, at the\n * moment of the event. Company-installed apps only.\n */\nexport interface WebhookInvestorTotals {\n active_investment_count: number;\n total_committed: number | string | null;\n latest_applied_at: string | null;\n investor_status: \"active\" | \"none_active\";\n}\n\n/** `data` for the `investment.*` lifecycle events (not `investment.changed`). */\nexport interface InvestmentEventData {\n /** The investment (`inv_…`). */\n id: string;\n status: \"reserved\" | \"active\" | \"executed\" | \"canceled\" | \"converted\";\n /** The offering (`ofr_…`). */\n offering: string | null;\n amounts: { committed: number | string | null };\n investor: WebhookInvestor;\n /** Company-installed apps only. Absent for user-connected apps. */\n investor_totals?: WebhookInvestorTotals;\n /** ISO 8601 with microseconds. Order events by this, not by arrival. Absent on `investment.executed`. */\n occurred_at?: string;\n /** `investment.canceled` only. */\n canceled_at?: string | null;\n /** `investment.converted` only — the successor (`inv_…`), or null if unresolved at conversion. */\n converted_to?: string | null;\n /** `investment.amount_changed` only. */\n previous_amounts?: { committed: number | string | null };\n}\n\n/** `data` for `investment.changed` — a thin sync nudge; fetch the record, don't trust the payload. */\nexport interface InvestmentChangedEventData {\n /** The investment (`inv_…`). */\n id: string;\n /** `false` means the investment is no longer visible to the company (a tombstone). */\n visible: boolean;\n reason: string;\n /** The company (`co_…`). */\n company: string | null;\n observed_at: string;\n}\n\n/** `data` for the `offering.*` events. */\nexport interface OfferingEventData {\n /** The offering (`ofr_…`). */\n offering: string | null;\n status: \"open\" | \"closing\" | \"closed\" | \"canceled\";\n company: { name: string | null; url: string | null };\n /** `offering.closing` only, when ops has an ETA for disbursement. */\n expected_disbursement_at?: string;\n}\n\n/** `data` for the `investment_session.*` events. */\nexport interface InvestmentSessionEventData {\n /** The session id. */\n id: string;\n status: string;\n /** The offering (`ofr_…`). */\n offering: string | null;\n email: string | null;\n allocation_cents: number | null;\n expires_at: string | null;\n /** The resulting investment (`inv_…`), once one exists. */\n investment?: string;\n}\n\n/** `data` for `syndicate_member.invited` / `syndicate_member.reinvited`. */\nexport interface SyndicateInvitationEventData {\n /** The syndicate (`syn_…`). */\n syndicate: string | null;\n email: string | null;\n name: string | null;\n /** The invitee's `usr_…` id when the address already belongs to an account, else null. */\n user: string | null;\n invited_by: WebhookPersonRef | null;\n occurred_at: string;\n}\n\n/** `data` for `syndicate_member.applied` / `.approved` / `.joined`. */\nexport interface SyndicateMemberEventData {\n /** The membership (`mem_…`). */\n id: string | null;\n /** The syndicate (`syn_…`). */\n syndicate: string | null;\n status: \"pending\" | \"approved\" | \"member\";\n user: { id: string | null; name: string | null; email: string | null };\n /** Null on an automatic or invited join. */\n approved_by: WebhookPersonRef | null;\n occurred_at: string;\n}\n\n/** Maps each event name to the documented shape of its `data`. */\nexport interface WebhookEventDataMap {\n \"investment.created\": InvestmentEventData;\n \"investment.reinstated\": InvestmentEventData;\n \"investment.canceled\": InvestmentEventData;\n \"investment.converted\": InvestmentEventData;\n \"investment.amount_changed\": InvestmentEventData;\n \"investment.executed\": InvestmentEventData;\n \"investment.changed\": InvestmentChangedEventData;\n \"offering.opened\": OfferingEventData;\n \"offering.closing\": OfferingEventData;\n \"offering.closed\": OfferingEventData;\n \"offering.canceled\": OfferingEventData;\n \"investment_session.created\": InvestmentSessionEventData;\n \"investment_session.started\": InvestmentSessionEventData;\n \"investment_session.completed\": InvestmentSessionEventData;\n \"investment_session.expired\": InvestmentSessionEventData;\n \"investment_session.canceled\": InvestmentSessionEventData;\n \"syndicate_member.invited\": SyndicateInvitationEventData;\n \"syndicate_member.reinvited\": SyndicateInvitationEventData;\n \"syndicate_member.applied\": SyndicateMemberEventData;\n \"syndicate_member.approved\": SyndicateMemberEventData;\n \"syndicate_member.joined\": SyndicateMemberEventData;\n}\n\n// Compile-time check: every catalog name has a payload type. If a spec sync adds\n// an event, `npm run typecheck` fails here until the map is extended.\ntype EveryEventIsTyped = WebhookEventName extends keyof WebhookEventDataMap ? true : never;\nconst everyEventIsTyped: EveryEventIsTyped = true;\nvoid everyEventIsTyped;\n\n/**\n * A verified, parsed delivery. Narrow on `event` to get a typed `data`:\n *\n * if (evt.event === \"investment.executed\") evt.data.amounts.committed\n */\nexport type WebhookEvent<E extends WebhookEventName = WebhookEventName> = {\n [K in E]: {\n /** Event id (`evt_…`) — the dedup key. Deliveries may repeat; ignore ids you've seen. */\n id: string;\n event: K;\n created_at: string;\n mode: WebhookMode;\n data: WebhookEventDataMap[K];\n /** The signed timestamp (`t`, unix seconds). */\n timestamp: number;\n };\n}[E];\n\n/**\n * A delivery whose `event` isn't in this SDK's catalog (newer than your installed\n * version). Still signature-verified; `data` is untyped.\n */\nexport interface UnknownWebhookEvent {\n id: string;\n event: string;\n created_at: string;\n mode: WebhookMode;\n data: unknown;\n timestamp: number;\n}\n\n// ---------------------------------------------------------------------------\n// Headers + errors\n// ---------------------------------------------------------------------------\n\n/** The platform-events signature header (case-insensitive). */\nexport const SIGNATURE_HEADER = \"wefunder-signature\";\n/** Documented consumer replay tolerance. */\nexport const DEFAULT_TOLERANCE_SECONDS = 300;\n\n/** @deprecated Attribution-era header; only relevant to legacy attribution subscriptions. */\nexport const LEGACY_SIGNATURE_HEADER = \"x-wefunder-signature\";\n/** @deprecated Attribution-era header; only relevant to legacy attribution subscriptions. */\nexport const LEGACY_TIMESTAMP_HEADER = \"x-wefunder-timestamp\";\n/** @deprecated Attribution-era header; only relevant to legacy attribution subscriptions. */\nexport const LEGACY_EVENT_HEADER = \"x-wefunder-event\";\n/** @deprecated Attribution-era header; only relevant to legacy attribution subscriptions. */\nexport const LEGACY_DELIVERY_ID_HEADER = \"x-wefunder-delivery-id\";\n\nexport type WebhookSignatureFailure =\n | \"missing_header\"\n | \"malformed_header\"\n | \"timestamp_out_of_tolerance\"\n | \"signature_mismatch\"\n | \"invalid_payload\";\n\n/** Thrown by `constructEvent` / `constructEventFromRequest`. Respond 400 and don't process. */\nexport class WebhookSignatureError extends Error {\n readonly reason: WebhookSignatureFailure;\n constructor(reason: WebhookSignatureFailure, message: string) {\n super(message);\n this.name = \"WebhookSignatureError\";\n this.reason = reason;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Signing primitives\n// ---------------------------------------------------------------------------\n\nexport type RawBody = string | Uint8Array;\n\nfunction bodyBuffer(payload: RawBody): Buffer {\n return typeof payload === \"string\" ? Buffer.from(payload, \"utf8\") : Buffer.from(payload);\n}\n\n/** `HMAC-SHA256(secret, \"<timestamp>.<rawBody>\")` as lowercase hex. */\nexport function computeWebhookSignature(secret: string, timestamp: number | string, payload: RawBody): string {\n return createHmac(\"sha256\", secret).update(`${timestamp}.`).update(bodyBuffer(payload)).digest(\"hex\");\n}\n\nfunction constantTimeEqual(a: string, b: string): boolean {\n const ab = Buffer.from(a);\n const bb = Buffer.from(b);\n if (ab.length !== bb.length) return false;\n return timingSafeEqual(ab, bb);\n}\n\n/** The parts of a `Wefunder-Signature` header. */\nexport interface ParsedSignatureHeader {\n timestamp: number;\n /** Every `v1` value (more than one during a secret rotation). */\n signatures: string[];\n}\n\n/** Parse `t=<unix>,v1=<hex>[,v1=<hex>]`. Returns null when the shape is wrong. */\nexport function parseSignatureHeader(header: string): ParsedSignatureHeader | null {\n let timestamp: number | undefined;\n const signatures: string[] = [];\n for (const part of header.split(\",\")) {\n const eq = part.indexOf(\"=\");\n if (eq < 0) continue;\n const key = part.slice(0, eq).trim();\n const value = part.slice(eq + 1).trim();\n if (key === \"t\") {\n if (!/^\\d+$/.test(value)) return null;\n timestamp = Number(value);\n } else if (key === \"v1\" && value) {\n signatures.push(value);\n }\n // Unknown keys (a future `v2`) are ignored on purpose — forward compatible.\n }\n if (timestamp === undefined || signatures.length === 0) return null;\n return { timestamp, signatures };\n}\n\nexport interface SignWebhookOptions {\n /** The exact bytes that will be sent as the body. */\n payload: RawBody;\n secret: string;\n /** Unix seconds. Defaults to now. */\n timestamp?: number;\n /**\n * Extra secrets to also sign with (adds one `v1` per secret) — simulates a\n * rotation window in tests.\n */\n additionalSecrets?: string[];\n}\n\n/**\n * Build a `Wefunder-Signature` header value for `payload`. For your own tests\n * (sign a fixture, POST it at your handler) — the API signs real deliveries.\n */\nexport function signWebhook(opts: SignWebhookOptions): string {\n const t = opts.timestamp ?? Math.floor(Date.now() / 1000);\n const secrets = [opts.secret, ...(opts.additionalSecrets ?? [])];\n const entries = secrets.map((s) => `v1=${computeWebhookSignature(s, t, opts.payload)}`);\n return [`t=${t}`, ...entries].join(\",\");\n}\n\n// ---------------------------------------------------------------------------\n// Verification\n// ---------------------------------------------------------------------------\n\nexport interface VerifyWebhookOptions {\n /** The exact raw request body (NOT a re-serialized object). */\n payload: RawBody;\n /** Value of the `Wefunder-Signature` header (`t=…,v1=…`). */\n header: string;\n secret: string;\n /** Reject if |now - t| exceeds this. Default 300s. Set 0 to disable. */\n toleranceSeconds?: number;\n /** Injectable clock (ms since epoch), for tests. */\n now?: () => number;\n}\n\n/**\n * Returns the reason a delivery is NOT valid, or null when it is. Constant-time\n * compare against every `v1`; enforces the timestamp tolerance.\n */\nexport function checkWebhookSignature(opts: VerifyWebhookOptions): WebhookSignatureFailure | null {\n const parsed = parseSignatureHeader(opts.header);\n if (!parsed) return \"malformed_header\";\n const tolerance = opts.toleranceSeconds ?? DEFAULT_TOLERANCE_SECONDS;\n if (tolerance > 0) {\n const nowSec = (opts.now ?? Date.now)() / 1000;\n if (Math.abs(nowSec - parsed.timestamp) > tolerance) return \"timestamp_out_of_tolerance\";\n }\n const expected = computeWebhookSignature(opts.secret, parsed.timestamp, opts.payload);\n return parsed.signatures.some((sig) => constantTimeEqual(sig, expected)) ? null : \"signature_mismatch\";\n}\n\n/** Legacy attribution-scheme inputs (`X-Wefunder-Signature: sha256=…` + `X-Wefunder-Timestamp`). */\nexport interface VerifyLegacyWebhookOptions {\n payload: RawBody;\n /** `sha256=<hex>` */\n signature: string;\n /** Unix seconds, from `X-Wefunder-Timestamp`. */\n timestamp: string | number;\n secret: string;\n toleranceSeconds?: number;\n now?: () => number;\n}\n\n/**\n * `true` iff the signature is valid and (when tolerance > 0) the timestamp is\n * within tolerance. Never throws — respond 400 without a try/catch.\n *\n * Accepts either the platform-events header (`{ header }`) or, for a legacy\n * attribution subscription, `{ signature, timestamp }`.\n */\nexport function verifyWebhook(opts: VerifyWebhookOptions | VerifyLegacyWebhookOptions): boolean {\n if (\"header\" in opts) return checkWebhookSignature(opts) === null;\n return verifyLegacyWebhook(opts);\n}\n\nfunction verifyLegacyWebhook(opts: VerifyLegacyWebhookOptions): boolean {\n const tolerance = opts.toleranceSeconds ?? DEFAULT_TOLERANCE_SECONDS;\n const ts = Number(opts.timestamp);\n if (!Number.isFinite(ts)) return false;\n if (tolerance > 0 && Math.abs((opts.now ?? Date.now)() / 1000 - ts) > tolerance) return false;\n const expected = `sha256=${computeWebhookSignature(opts.secret, opts.timestamp, opts.payload)}`;\n return constantTimeEqual(opts.signature, expected);\n}\n\n// ---------------------------------------------------------------------------\n// constructEvent — verify + parse\n// ---------------------------------------------------------------------------\n\n/** Node `IncomingHttpHeaders`, a fetch `Headers`, or a plain object. */\nexport type HeadersLike = Headers | Record<string, string | string[] | undefined>;\n\nfunction headerGetter(headers: HeadersLike | string): (name: string) => string | undefined {\n if (typeof headers === \"string\") {\n return (name) => (name === SIGNATURE_HEADER ? headers : undefined);\n }\n if (headers instanceof Headers) return (name) => headers.get(name) ?? undefined;\n // Plain objects: try the lowercase key, then a case-insensitive scan\n // (Node lowercases IncomingHttpHeaders; hand-built objects may not).\n return (name) => {\n let v = headers[name];\n if (v === undefined) {\n const hit = Object.keys(headers).find((k) => k.toLowerCase() === name);\n if (hit) v = headers[hit];\n }\n return Array.isArray(v) ? v[0] : v;\n };\n}\n\nexport interface ConstructEventOptions {\n toleranceSeconds?: number;\n now?: () => number;\n}\n\ninterface Envelope {\n id?: unknown;\n event?: unknown;\n created_at?: unknown;\n mode?: unknown;\n data?: unknown;\n}\n\n/**\n * Verify a delivery and parse its envelope in one step. Throws\n * `WebhookSignatureError` on any failure so handlers fail loudly; on success the\n * returned event is a discriminated union — narrow on `event` for typed `data`.\n *\n * @param payload the RAW request body (string or bytes) — never a re-serialized object\n * @param headers the request headers, or the `Wefunder-Signature` value itself\n * @param secret the endpoint's signing secret (shown once at create / rotate)\n */\nexport function constructEvent(\n payload: RawBody,\n headers: HeadersLike | string,\n secret: string,\n opts?: ConstructEventOptions,\n): WebhookEvent | UnknownWebhookEvent {\n const get = headerGetter(headers);\n const header = get(SIGNATURE_HEADER);\n\n if (!header) {\n const legacySig = get(LEGACY_SIGNATURE_HEADER);\n const legacyTs = get(LEGACY_TIMESTAMP_HEADER);\n if (legacySig && legacyTs) return constructLegacyEvent(payload, get, legacySig, legacyTs, secret, opts);\n throw new WebhookSignatureError(\"missing_header\", describeFailure(\"missing_header\"));\n }\n\n const failure = checkWebhookSignature({ payload, header, secret, ...opts });\n if (failure) throw new WebhookSignatureError(failure, describeFailure(failure));\n\n const parsed = parseSignatureHeader(header)!;\n const env = parseEnvelope(payload);\n return {\n id: String(env.id ?? \"\"),\n event: String(env.event ?? \"\"),\n created_at: String(env.created_at ?? \"\"),\n mode: (env.mode === \"test\" ? \"test\" : \"live\") as WebhookMode,\n data: env.data,\n timestamp: parsed.timestamp,\n } as WebhookEvent | UnknownWebhookEvent;\n}\n\nfunction constructLegacyEvent(\n payload: RawBody,\n get: (name: string) => string | undefined,\n signature: string,\n timestamp: string,\n secret: string,\n opts?: ConstructEventOptions,\n): UnknownWebhookEvent {\n if (!verifyLegacyWebhook({ payload, signature, timestamp, secret, ...opts })) {\n throw new WebhookSignatureError(\"signature_mismatch\", describeFailure(\"signature_mismatch\"));\n }\n const env = parseEnvelope(payload);\n return {\n id: String(env.id ?? get(LEGACY_DELIVERY_ID_HEADER) ?? \"\"),\n event: String(env.event ?? get(LEGACY_EVENT_HEADER) ?? \"\"),\n created_at: String(env.created_at ?? \"\"),\n mode: (env.mode === \"test\" ? \"test\" : \"live\") as WebhookMode,\n data: env.data ?? env,\n timestamp: Number(timestamp),\n };\n}\n\nfunction parseEnvelope(payload: RawBody): Envelope {\n try {\n const parsed: unknown = JSON.parse(bodyBuffer(payload).toString(\"utf8\"));\n if (parsed === null || typeof parsed !== \"object\") throw new Error(\"not an object\");\n return parsed as Envelope;\n } catch {\n throw new WebhookSignatureError(\"invalid_payload\", describeFailure(\"invalid_payload\"));\n }\n}\n\nfunction describeFailure(reason: WebhookSignatureFailure): string {\n switch (reason) {\n case \"missing_header\":\n return \"Missing Wefunder-Signature header\";\n case \"malformed_header\":\n return \"Wefunder-Signature header is malformed (expected t=<unix>,v1=<hex>)\";\n case \"timestamp_out_of_tolerance\":\n return \"Webhook timestamp is outside the replay tolerance\";\n case \"signature_mismatch\":\n return \"Webhook signature verification failed\";\n case \"invalid_payload\":\n return \"Webhook body is not a JSON object\";\n }\n}\n\n/**\n * `constructEvent` for fetch-style servers (Next.js route handlers, Hono, Remix,\n * Cloudflare Workers, Bun, Deno): reads the raw body from the `Request` for you.\n * Don't call `request.json()` first — the body must be read exactly once, as text.\n */\nexport async function constructEventFromRequest(\n request: Request,\n secret: string,\n opts?: ConstructEventOptions,\n): Promise<WebhookEvent | UnknownWebhookEvent> {\n const payload = await request.text();\n return constructEvent(payload, request.headers, secret, opts);\n}\n\n// ---------------------------------------------------------------------------\n// Dispatch — route a verified event to typed handlers\n// ---------------------------------------------------------------------------\n\nexport type WebhookHandlers = {\n [K in WebhookEventName]?: (event: WebhookEvent<K>) => void | Promise<void>;\n} & {\n /** Runs for any event with no specific handler (including names newer than this SDK). */\n default?: (event: WebhookEvent | UnknownWebhookEvent) => void | Promise<void>;\n};\n\n/**\n * Call the handler registered for `event.event`, falling back to `default`.\n * Returns `true` if a handler ran. Pairs with `constructEvent`:\n *\n * const event = constructEvent(raw, req.headers, secret);\n * await dispatchWebhook(event, {\n * \"investment.executed\": async (e) => await recordFunding(e.data),\n * default: (e) => console.log(\"unhandled\", e.event),\n * });\n */\nexport async function dispatchWebhook(\n event: WebhookEvent | UnknownWebhookEvent,\n handlers: WebhookHandlers,\n): Promise<boolean> {\n type AnyHandler = (e: never) => void | Promise<void>;\n const specific =\n event.event === \"default\"\n ? undefined\n : (handlers as Record<string, AnyHandler | undefined>)[event.event];\n if (specific) {\n await specific(event as never);\n return true;\n }\n if (handlers.default) {\n await handlers.default(event);\n return true;\n }\n return false;\n}\n"],"mappings":"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","names":["joinedValues","config","request","url"]}
|
|
1
|
+
{"version":3,"sources":["../src/generated/core/bodySerializer.gen.ts","../src/generated/core/params.gen.ts","../src/generated/core/serverSentEvents.gen.ts","../src/generated/core/pathSerializer.gen.ts","../src/generated/core/utils.gen.ts","../src/generated/core/auth.gen.ts","../src/generated/client/utils.gen.ts","../src/generated/client/client.gen.ts","../src/http.ts","../src/oauth.ts","../src/errors.ts","../src/token-manager.ts","../src/pagination.ts","../src/generated/sdk.gen.ts","../src/generated/client.gen.ts","../src/client.ts","../src/webhooks.ts"],"sourcesContent":["// This file is auto-generated by @hey-api/openapi-ts\n\nimport type {\n ArrayStyle,\n ObjectStyle,\n SerializerOptions,\n} from \"./pathSerializer.gen\";\n\nexport type QuerySerializer = (query: Record<string, unknown>) => string;\n\nexport type BodySerializer = (body: unknown) => unknown;\n\ntype QuerySerializerOptionsObject = {\n allowReserved?: boolean;\n array?: Partial<SerializerOptions<ArrayStyle>>;\n object?: Partial<SerializerOptions<ObjectStyle>>;\n};\n\nexport type QuerySerializerOptions = QuerySerializerOptionsObject & {\n /**\n * Per-parameter serialization overrides. When provided, these settings\n * override the global array/object settings for specific parameter names.\n */\n parameters?: Record<string, QuerySerializerOptionsObject>;\n};\n\nconst serializeFormDataPair = (\n data: FormData,\n key: string,\n value: unknown,\n): void => {\n if (typeof value === \"string\" || value instanceof Blob) {\n data.append(key, value);\n } else if (value instanceof Date) {\n data.append(key, value.toISOString());\n } else {\n data.append(key, JSON.stringify(value));\n }\n};\n\nconst serializeUrlSearchParamsPair = (\n data: URLSearchParams,\n key: string,\n value: unknown,\n): void => {\n if (typeof value === \"string\") {\n data.append(key, value);\n } else {\n data.append(key, JSON.stringify(value));\n }\n};\n\nexport const formDataBodySerializer = {\n bodySerializer: (body: unknown): FormData => {\n const data = new FormData();\n\n Object.entries(body as Record<string, unknown>).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n if (Array.isArray(value)) {\n value.forEach((v) => serializeFormDataPair(data, key, v));\n } else {\n serializeFormDataPair(data, key, value);\n }\n });\n\n return data;\n },\n};\n\nexport const jsonBodySerializer = {\n bodySerializer: (body: unknown): string =>\n JSON.stringify(body, (_key, value) =>\n typeof value === \"bigint\" ? value.toString() : value,\n ),\n};\n\nexport const urlSearchParamsBodySerializer = {\n bodySerializer: (body: unknown): string => {\n const data = new URLSearchParams();\n\n Object.entries(body as Record<string, unknown>).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n if (Array.isArray(value)) {\n value.forEach((v) => serializeUrlSearchParamsPair(data, key, v));\n } else {\n serializeUrlSearchParamsPair(data, key, value);\n }\n });\n\n return data.toString();\n },\n};\n","// This file is auto-generated by @hey-api/openapi-ts\n\ntype Slot = \"body\" | \"headers\" | \"path\" | \"query\";\n\nexport type Field =\n | {\n in: Exclude<Slot, \"body\">;\n /**\n * Field name. This is the name we want the user to see and use.\n */\n key: string;\n /**\n * Field mapped name. This is the name we want to use in the request.\n * If omitted, we use the same value as `key`.\n */\n map?: string;\n }\n | {\n in: Extract<Slot, \"body\">;\n /**\n * Key isn't required for bodies.\n */\n key?: string;\n map?: string;\n }\n | {\n /**\n * Field name. This is the name we want the user to see and use.\n */\n key: string;\n /**\n * Field mapped name. This is the name we want to use in the request.\n * If `in` is omitted, `map` aliases `key` to the transport layer.\n */\n map: Slot;\n };\n\nexport interface Fields {\n allowExtra?: Partial<Record<Slot, boolean>>;\n args?: ReadonlyArray<Field>;\n}\n\nexport type FieldsConfig = ReadonlyArray<Field | Fields>;\n\nconst extraPrefixesMap: Record<string, Slot> = {\n $body_: \"body\",\n $headers_: \"headers\",\n $path_: \"path\",\n $query_: \"query\",\n};\nconst extraPrefixes = Object.entries(extraPrefixesMap);\n\ntype KeyMap = Map<\n string,\n | {\n in: Slot;\n map?: string;\n }\n | {\n in?: never;\n map: Slot;\n }\n>;\n\nfunction buildKeyMap(fields: FieldsConfig, map?: KeyMap): KeyMap {\n if (!map) {\n map = new Map();\n }\n\n for (const config of fields) {\n if (\"in\" in config) {\n if (config.key) {\n map.set(config.key, {\n in: config.in,\n map: config.map,\n });\n }\n } else if (\"key\" in config) {\n map.set(config.key, {\n map: config.map,\n });\n } else if (config.args) {\n buildKeyMap(config.args, map);\n }\n }\n\n return map;\n}\n\ninterface Params {\n body?: unknown;\n headers: Record<string, unknown>;\n path: Record<string, unknown>;\n query: Record<string, unknown>;\n}\n\nfunction stripEmptySlots(params: Params): void {\n for (const [slot, value] of Object.entries(params)) {\n if (slot === \"body\") continue;\n if (\n value &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n !Object.keys(value).length\n ) {\n delete params[slot as Slot];\n }\n }\n}\n\nexport function buildClientParams(\n args: ReadonlyArray<unknown>,\n fields: FieldsConfig,\n): Params {\n const params: Params = {\n headers: Object.create(null),\n path: Object.create(null),\n query: Object.create(null),\n };\n\n const map = buildKeyMap(fields);\n\n function writeSlot(slot: Slot, key: string, value: unknown): void {\n let record = params[slot] as Record<string, unknown> | undefined;\n if (record === undefined) {\n record = Object.create(null) as Record<string, unknown>;\n params[slot] = record;\n }\n record[key] = value;\n }\n\n let config: FieldsConfig[number] | undefined;\n\n for (const [index, arg] of args.entries()) {\n if (fields[index]) {\n config = fields[index];\n }\n\n if (!config) {\n continue;\n }\n\n if (\"in\" in config) {\n if (config.key) {\n const field = map.get(config.key)!;\n const name = field.map || config.key;\n if (field.in) {\n writeSlot(field.in, name, arg);\n }\n } else {\n params.body = arg;\n }\n } else {\n for (const [key, value] of Object.entries(arg ?? {})) {\n const field = map.get(key);\n\n if (field) {\n if (field.in) {\n const name = field.map || key;\n writeSlot(field.in, name, value);\n } else {\n params[field.map] = value;\n }\n } else {\n const extra = extraPrefixes.find(([prefix]) =>\n key.startsWith(prefix),\n );\n\n if (extra) {\n const [prefix, slot] = extra;\n writeSlot(slot, key.slice(prefix.length), value);\n } else if (\"allowExtra\" in config && config.allowExtra) {\n for (const [slot, allowed] of Object.entries(config.allowExtra)) {\n if (allowed) {\n writeSlot(slot as Slot, key, value);\n break;\n }\n }\n }\n }\n }\n }\n }\n\n stripEmptySlots(params);\n\n return params;\n}\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { Config } from \"./types.gen\";\n\nexport type ServerSentEventsOptions<TData = unknown> = Omit<\n RequestInit,\n \"method\"\n> &\n Pick<Config, \"method\" | \"responseTransformer\" | \"responseValidator\"> & {\n /**\n * Fetch API implementation. You can use this option to provide a custom\n * fetch instance.\n *\n * @default globalThis.fetch\n */\n fetch?: typeof fetch;\n /**\n * Implementing clients can call request interceptors inside this hook.\n */\n onRequest?: (url: string, init: RequestInit) => Promise<Request>;\n /**\n * Callback invoked when a network or parsing error occurs during streaming.\n *\n * This option applies only if the endpoint returns a stream of events.\n *\n * @param error The error that occurred.\n */\n onSseError?: (error: unknown) => void;\n /**\n * Callback invoked when an event is streamed from the server.\n *\n * This option applies only if the endpoint returns a stream of events.\n *\n * @param event Event streamed from the server.\n * @returns Nothing (void).\n */\n onSseEvent?: (event: StreamEvent<TData>) => void;\n serializedBody?: RequestInit[\"body\"];\n /**\n * Default retry delay in milliseconds.\n *\n * This option applies only if the endpoint returns a stream of events.\n *\n * @default 3000\n */\n sseDefaultRetryDelay?: number;\n /**\n * Maximum number of retry attempts before giving up.\n */\n sseMaxRetryAttempts?: number;\n /**\n * Maximum retry delay in milliseconds.\n *\n * Applies only when exponential backoff is used.\n *\n * This option applies only if the endpoint returns a stream of events.\n *\n * @default 30000\n */\n sseMaxRetryDelay?: number;\n /**\n * Optional sleep function for retry backoff.\n *\n * Defaults to using `setTimeout`.\n */\n sseSleepFn?: (ms: number) => Promise<void>;\n url: string;\n };\n\nexport interface StreamEvent<TData = unknown> {\n data: TData;\n event?: string;\n id?: string;\n retry?: number;\n}\n\nexport type ServerSentEventsResult<\n TData = unknown,\n TReturn = void,\n TNext = unknown,\n> = {\n stream: AsyncGenerator<\n TData extends Record<string, unknown> ? TData[keyof TData] : TData,\n TReturn,\n TNext\n >;\n};\n\nexport function createSseClient<TData = unknown>({\n onRequest,\n onSseError,\n onSseEvent,\n responseTransformer,\n responseValidator,\n sseDefaultRetryDelay,\n sseMaxRetryAttempts,\n sseMaxRetryDelay,\n sseSleepFn,\n url,\n ...options\n}: ServerSentEventsOptions): ServerSentEventsResult<TData> {\n let lastEventId: string | undefined;\n\n const sleep =\n sseSleepFn ??\n ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms)));\n\n const createStream = async function* () {\n let retryDelay: number = sseDefaultRetryDelay ?? 3000;\n let attempt = 0;\n const signal = options.signal ?? new AbortController().signal;\n\n while (true) {\n if (signal.aborted) break;\n\n attempt++;\n\n const headers =\n options.headers instanceof Headers\n ? options.headers\n : new Headers(options.headers as Record<string, string> | undefined);\n\n if (lastEventId !== undefined) {\n headers.set(\"Last-Event-ID\", lastEventId);\n }\n\n try {\n const requestInit: RequestInit = {\n redirect: \"follow\",\n ...options,\n body: options.serializedBody,\n headers,\n signal,\n };\n let request = new Request(url, requestInit);\n if (onRequest) {\n request = await onRequest(url, requestInit);\n }\n // fetch must be assigned here, otherwise it would throw the error:\n // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation\n const _fetch = options.fetch ?? globalThis.fetch;\n const response = await _fetch(request);\n\n if (!response.ok)\n throw new Error(\n `SSE failed: ${response.status} ${response.statusText}`,\n );\n\n if (!response.body) throw new Error(\"No body in SSE response\");\n\n const reader = response.body\n .pipeThrough(new TextDecoderStream())\n .getReader();\n\n let buffer = \"\";\n\n const abortHandler = () => {\n try {\n reader.cancel();\n } catch {\n // noop\n }\n };\n\n signal.addEventListener(\"abort\", abortHandler);\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += value;\n buffer = buffer.replace(/\\r\\n?/g, \"\\n\"); // normalize line endings\n\n const chunks = buffer.split(\"\\n\\n\");\n buffer = chunks.pop() ?? \"\";\n\n for (const chunk of chunks) {\n const lines = chunk.split(\"\\n\");\n const dataLines: Array<string> = [];\n let eventName: string | undefined;\n\n for (const line of lines) {\n if (line.startsWith(\"data:\")) {\n dataLines.push(line.replace(/^data:\\s*/, \"\"));\n } else if (line.startsWith(\"event:\")) {\n eventName = line.replace(/^event:\\s*/, \"\");\n } else if (line.startsWith(\"id:\")) {\n lastEventId = line.replace(/^id:\\s*/, \"\");\n } else if (line.startsWith(\"retry:\")) {\n const parsed = Number.parseInt(\n line.replace(/^retry:\\s*/, \"\"),\n 10,\n );\n if (!Number.isNaN(parsed)) {\n retryDelay = parsed;\n }\n }\n }\n\n let data: unknown;\n let parsedJson = false;\n\n if (dataLines.length) {\n const rawData = dataLines.join(\"\\n\");\n try {\n data = JSON.parse(rawData);\n parsedJson = true;\n } catch {\n data = rawData;\n }\n }\n\n if (parsedJson) {\n if (responseValidator) {\n await responseValidator(data);\n }\n\n if (responseTransformer) {\n data = await responseTransformer(data);\n }\n }\n\n onSseEvent?.({\n data,\n event: eventName,\n id: lastEventId,\n retry: retryDelay,\n });\n\n if (dataLines.length) {\n yield data as any;\n }\n }\n }\n } finally {\n signal.removeEventListener(\"abort\", abortHandler);\n reader.releaseLock();\n }\n\n break; // exit loop on normal completion\n } catch (error) {\n // connection failed or aborted; retry after delay\n onSseError?.(error);\n\n if (\n sseMaxRetryAttempts !== undefined &&\n attempt >= sseMaxRetryAttempts\n ) {\n break; // stop after firing error\n }\n\n // exponential backoff: double retry each attempt, cap at 30s\n const backoff = Math.min(\n retryDelay * 2 ** (attempt - 1),\n sseMaxRetryDelay ?? 30000,\n );\n await sleep(backoff);\n }\n }\n };\n\n const stream = createStream();\n\n return { stream };\n}\n","// This file is auto-generated by @hey-api/openapi-ts\n\ninterface SerializeOptions<T>\n extends SerializePrimitiveOptions, SerializerOptions<T> {}\n\ninterface SerializePrimitiveOptions {\n allowReserved?: boolean;\n name: string;\n}\n\nexport interface SerializerOptions<T> {\n /**\n * @default true\n */\n explode: boolean;\n style: T;\n}\n\nexport type ArrayStyle = \"form\" | \"spaceDelimited\" | \"pipeDelimited\";\nexport type ArraySeparatorStyle = ArrayStyle | MatrixStyle;\ntype MatrixStyle = \"label\" | \"matrix\" | \"simple\";\nexport type ObjectStyle = \"form\" | \"deepObject\";\ntype ObjectSeparatorStyle = ObjectStyle | MatrixStyle;\n\ninterface SerializePrimitiveParam extends SerializePrimitiveOptions {\n value: string;\n}\n\nexport const separatorArrayExplode = (\n style: ArraySeparatorStyle,\n): \".\" | \";\" | \",\" | \"&\" => {\n switch (style) {\n case \"label\":\n return \".\";\n case \"matrix\":\n return \";\";\n case \"simple\":\n return \",\";\n default:\n return \"&\";\n }\n};\n\nexport const separatorArrayNoExplode = (\n style: ArraySeparatorStyle,\n): \",\" | \"|\" | \"%20\" => {\n switch (style) {\n case \"form\":\n return \",\";\n case \"pipeDelimited\":\n return \"|\";\n case \"spaceDelimited\":\n return \"%20\";\n default:\n return \",\";\n }\n};\n\nexport const separatorObjectExplode = (\n style: ObjectSeparatorStyle,\n): \".\" | \";\" | \",\" | \"&\" => {\n switch (style) {\n case \"label\":\n return \".\";\n case \"matrix\":\n return \";\";\n case \"simple\":\n return \",\";\n default:\n return \"&\";\n }\n};\n\nexport const serializeArrayParam = ({\n allowReserved,\n explode,\n name,\n style,\n value,\n}: SerializeOptions<ArraySeparatorStyle> & {\n value: unknown[];\n}): string => {\n if (!explode) {\n const joinedValues = (\n allowReserved ? value : value.map((v) => encodeURIComponent(v as string))\n ).join(separatorArrayNoExplode(style));\n switch (style) {\n case \"label\":\n return `.${joinedValues}`;\n case \"matrix\":\n return `;${name}=${joinedValues}`;\n case \"simple\":\n return joinedValues;\n default:\n return `${name}=${joinedValues}`;\n }\n }\n\n const separator = separatorArrayExplode(style);\n const joinedValues = value\n .map((v) => {\n if (style === \"label\" || style === \"simple\") {\n return allowReserved ? v : encodeURIComponent(v as string);\n }\n\n return serializePrimitiveParam({\n allowReserved,\n name,\n value: v as string,\n });\n })\n .join(separator);\n return style === \"label\" || style === \"matrix\"\n ? separator + joinedValues\n : joinedValues;\n};\n\nexport const serializePrimitiveParam = ({\n allowReserved,\n name,\n value,\n}: SerializePrimitiveParam): string => {\n if (value === undefined || value === null) {\n return \"\";\n }\n\n if (typeof value === \"object\") {\n throw new Error(\n \"Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.\",\n );\n }\n\n return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;\n};\n\nexport const serializeObjectParam = ({\n allowReserved,\n explode,\n name,\n style,\n value,\n valueOnly,\n}: SerializeOptions<ObjectSeparatorStyle> & {\n value: Record<string, unknown> | Date;\n valueOnly?: boolean;\n}): string => {\n if (value instanceof Date) {\n return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;\n }\n\n if (style !== \"deepObject\" && !explode) {\n let values: string[] = [];\n Object.entries(value).forEach(([key, v]) => {\n values = [\n ...values,\n key,\n allowReserved ? (v as string) : encodeURIComponent(v as string),\n ];\n });\n const joinedValues = values.join(\",\");\n switch (style) {\n case \"form\":\n return `${name}=${joinedValues}`;\n case \"label\":\n return `.${joinedValues}`;\n case \"matrix\":\n return `;${name}=${joinedValues}`;\n default:\n return joinedValues;\n }\n }\n\n const separator = separatorObjectExplode(style);\n const joinedValues = Object.entries(value)\n .map(([key, v]) =>\n serializePrimitiveParam({\n allowReserved,\n name: style === \"deepObject\" ? `${name}[${key}]` : key,\n value: v as string,\n }),\n )\n .join(separator);\n return style === \"label\" || style === \"matrix\"\n ? separator + joinedValues\n : joinedValues;\n};\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { BodySerializer, QuerySerializer } from \"./bodySerializer.gen\";\nimport {\n type ArraySeparatorStyle,\n serializeArrayParam,\n serializeObjectParam,\n serializePrimitiveParam,\n} from \"./pathSerializer.gen\";\n\nexport interface PathSerializer {\n path: Record<string, unknown>;\n url: string;\n}\n\nexport const PATH_PARAM_RE: RegExp = /\\{[^{}]+\\}/g;\n\nexport const defaultPathSerializer = ({\n path,\n url: _url,\n}: PathSerializer): string => {\n let url = _url;\n const matches = _url.match(PATH_PARAM_RE);\n if (matches) {\n for (const match of matches) {\n let explode = false;\n let name = match.substring(1, match.length - 1);\n let style: ArraySeparatorStyle = \"simple\";\n\n if (name.endsWith(\"*\")) {\n explode = true;\n name = name.substring(0, name.length - 1);\n }\n\n if (name.startsWith(\".\")) {\n name = name.substring(1);\n style = \"label\";\n } else if (name.startsWith(\";\")) {\n name = name.substring(1);\n style = \"matrix\";\n }\n\n const value = path[name];\n\n if (value === undefined || value === null) {\n continue;\n }\n\n if (Array.isArray(value)) {\n url = url.replace(\n match,\n serializeArrayParam({ explode, name, style, value }),\n );\n continue;\n }\n\n if (typeof value === \"object\") {\n url = url.replace(\n match,\n serializeObjectParam({\n explode,\n name,\n style,\n value: value as Record<string, unknown>,\n valueOnly: true,\n }),\n );\n continue;\n }\n\n if (style === \"matrix\") {\n url = url.replace(\n match,\n `;${serializePrimitiveParam({\n name,\n value: value as string,\n })}`,\n );\n continue;\n }\n\n const replaceValue = encodeURIComponent(\n style === \"label\" ? `.${value as string}` : (value as string),\n );\n url = url.replace(match, replaceValue);\n }\n }\n return url;\n};\n\nexport const getUrl = ({\n baseUrl,\n path,\n query,\n querySerializer,\n url: _url,\n}: {\n baseUrl?: string;\n path?: Record<string, unknown>;\n query?: Record<string, unknown>;\n querySerializer: QuerySerializer;\n url: string;\n}): string => {\n const pathUrl = _url.startsWith(\"/\") ? _url : `/${_url}`;\n let url = (baseUrl ?? \"\") + pathUrl;\n if (path) {\n url = defaultPathSerializer({ path, url });\n }\n let search = query ? querySerializer(query) : \"\";\n if (search.startsWith(\"?\")) {\n search = search.substring(1);\n }\n if (search) {\n url += `?${search}`;\n }\n return url;\n};\n\nexport function getValidRequestBody(options: {\n body?: unknown;\n bodySerializer?: BodySerializer | null;\n serializedBody?: unknown;\n}): unknown {\n const hasBody = options.body !== undefined;\n const isSerializedBody = hasBody && options.bodySerializer;\n\n if (isSerializedBody) {\n if (\"serializedBody\" in options) {\n const hasSerializedBody =\n options.serializedBody !== undefined && options.serializedBody !== \"\";\n\n return hasSerializedBody ? options.serializedBody : null;\n }\n\n // not all clients implement a serializedBody property (i.e., client-axios)\n return options.body !== \"\" ? options.body : null;\n }\n\n // plain/text body\n if (hasBody) {\n return options.body;\n }\n\n // no body was provided\n return undefined;\n}\n","// This file is auto-generated by @hey-api/openapi-ts\n\nexport type AuthToken = string | undefined;\n\nexport interface Auth {\n /**\n * Which part of the request do we use to send the auth?\n *\n * @default 'header'\n */\n in?: \"header\" | \"query\" | \"cookie\";\n /**\n * A unique identifier for the security scheme.\n *\n * Defined only when there are multiple security schemes whose `Auth`\n * shape would otherwise be identical.\n */\n key?: string;\n /**\n * Header or query parameter name.\n *\n * @default 'Authorization'\n */\n name?: string;\n scheme?: \"basic\" | \"bearer\";\n type: \"apiKey\" | \"http\";\n}\n\nexport const getAuthToken = async (\n auth: Auth,\n callback: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken,\n): Promise<string | undefined> => {\n const token =\n typeof callback === \"function\" ? await callback(auth) : callback;\n\n if (!token) {\n return;\n }\n\n if (auth.scheme === \"bearer\") {\n return `Bearer ${token}`;\n }\n\n if (auth.scheme === \"basic\") {\n return `Basic ${btoa(token)}`;\n }\n\n return token;\n};\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport { getAuthToken } from \"../core/auth.gen\";\nimport type { QuerySerializerOptions } from \"../core/bodySerializer.gen\";\nimport { jsonBodySerializer } from \"../core/bodySerializer.gen\";\nimport {\n serializeArrayParam,\n serializeObjectParam,\n serializePrimitiveParam,\n} from \"../core/pathSerializer.gen\";\nimport { getUrl } from \"../core/utils.gen\";\nimport type {\n Client,\n ClientOptions,\n Config,\n RequestOptions,\n} from \"./types.gen\";\n\nexport const createQuerySerializer = <T = unknown>({\n parameters = {},\n ...args\n}: QuerySerializerOptions = {}): ((queryParams: T) => string) => {\n const querySerializer = (queryParams: T): string => {\n const search: string[] = [];\n if (queryParams && typeof queryParams === \"object\") {\n for (const name in queryParams) {\n const value = queryParams[name];\n\n if (value === undefined || value === null) {\n continue;\n }\n\n const options = parameters[name] || args;\n\n if (Array.isArray(value)) {\n const serializedArray = serializeArrayParam({\n allowReserved: options.allowReserved,\n explode: true,\n name,\n style: \"form\",\n value,\n ...options.array,\n });\n if (serializedArray) search.push(serializedArray);\n } else if (typeof value === \"object\") {\n const serializedObject = serializeObjectParam({\n allowReserved: options.allowReserved,\n explode: true,\n name,\n style: \"deepObject\",\n value: value as Record<string, unknown>,\n ...options.object,\n });\n if (serializedObject) search.push(serializedObject);\n } else {\n const serializedPrimitive = serializePrimitiveParam({\n allowReserved: options.allowReserved,\n name,\n value: value as string,\n });\n if (serializedPrimitive) search.push(serializedPrimitive);\n }\n }\n }\n return search.join(\"&\");\n };\n return querySerializer;\n};\n\n/**\n * Infers parseAs value from provided Content-Type header.\n */\nexport const getParseAs = (\n contentType: string | null,\n): Exclude<Config[\"parseAs\"], \"auto\"> => {\n if (!contentType) {\n // If no Content-Type header is provided, the best we can do is return the raw response body,\n // which is effectively the same as the 'stream' option.\n return \"stream\";\n }\n\n const cleanContent = contentType.split(\";\")[0]?.trim();\n\n if (!cleanContent) {\n return;\n }\n\n if (\n cleanContent.startsWith(\"application/json\") ||\n cleanContent.endsWith(\"+json\")\n ) {\n return \"json\";\n }\n\n if (cleanContent === \"multipart/form-data\") {\n return \"formData\";\n }\n\n if (\n [\"application/\", \"audio/\", \"image/\", \"video/\"].some((type) =>\n cleanContent.startsWith(type),\n )\n ) {\n return \"blob\";\n }\n\n if (cleanContent.startsWith(\"text/\")) {\n return \"text\";\n }\n\n return;\n};\n\nconst checkForExistence = (\n options: Pick<RequestOptions, \"auth\" | \"query\"> & {\n headers: Headers;\n },\n name?: string,\n): boolean => {\n if (!name) {\n return false;\n }\n if (\n options.headers.has(name) ||\n options.query?.[name] ||\n options.headers.get(\"Cookie\")?.includes(`${name}=`)\n ) {\n return true;\n }\n return false;\n};\n\nexport async function setAuthParams(\n options: Pick<RequestOptions, \"auth\" | \"query\" | \"security\"> & {\n headers: Headers;\n },\n): Promise<void> {\n for (const auth of options.security ?? []) {\n if (checkForExistence(options, auth.name)) {\n continue;\n }\n\n const token = await getAuthToken(auth, options.auth);\n\n if (!token) {\n continue;\n }\n\n const name = auth.name ?? \"Authorization\";\n\n switch (auth.in) {\n case \"query\":\n if (!options.query) {\n options.query = {};\n }\n options.query[name] = token;\n break;\n case \"cookie\":\n options.headers.append(\"Cookie\", `${name}=${token}`);\n break;\n case \"header\":\n default:\n options.headers.set(name, token);\n break;\n }\n }\n}\n\nexport const buildUrl: Client[\"buildUrl\"] = (options) =>\n getUrl({\n baseUrl: options.baseUrl as string,\n path: options.path,\n query: options.query,\n querySerializer:\n typeof options.querySerializer === \"function\"\n ? options.querySerializer\n : createQuerySerializer(options.querySerializer),\n url: options.url,\n });\n\nexport const mergeConfigs = (a: Config, b: Config): Config => {\n const config = { ...a, ...b };\n if (config.baseUrl?.endsWith(\"/\")) {\n config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);\n }\n config.headers = mergeHeaders(a.headers, b.headers);\n return config;\n};\n\nconst headersEntries = (headers: Headers): Array<[string, string]> => {\n const entries: Array<[string, string]> = [];\n headers.forEach((value, key) => {\n entries.push([key, value]);\n });\n return entries;\n};\n\nexport const mergeHeaders = (\n ...headers: Array<Required<Config>[\"headers\"] | undefined>\n): Headers => {\n const mergedHeaders = new Headers();\n for (const header of headers) {\n if (!header) {\n continue;\n }\n\n const iterator =\n header instanceof Headers\n ? headersEntries(header)\n : Object.entries(header);\n\n for (const [key, value] of iterator) {\n if (value === null) {\n mergedHeaders.delete(key);\n } else if (Array.isArray(value)) {\n for (const v of value) {\n mergedHeaders.append(key, v as string);\n }\n } else if (value !== undefined) {\n // assume object headers are meant to be JSON stringified, i.e., their\n // content value in OpenAPI specification is 'application/json'\n mergedHeaders.set(\n key,\n typeof value === \"object\" ? JSON.stringify(value) : (value as string),\n );\n }\n }\n }\n return mergedHeaders;\n};\n\ntype ErrInterceptor<Err, Res, Req, Options> = (\n error: Err,\n /** response may be undefined due to a network error where no response object is produced */\n response: Res | undefined,\n /** request may be undefined, because error may be from building the request object itself */\n request: Req | undefined,\n options: Options,\n) => Err | Promise<Err>;\n\ntype ReqInterceptor<Req, Options> = (\n request: Req,\n options: Options,\n) => Req | Promise<Req>;\n\ntype ResInterceptor<Res, Req, Options> = (\n response: Res,\n request: Req,\n options: Options,\n) => Res | Promise<Res>;\n\nclass Interceptors<Interceptor> {\n fns: Array<Interceptor | null> = [];\n\n clear(): void {\n this.fns = [];\n }\n\n eject(id: number | Interceptor): void {\n const index = this.getInterceptorIndex(id);\n if (this.fns[index]) {\n this.fns[index] = null;\n }\n }\n\n exists(id: number | Interceptor): boolean {\n const index = this.getInterceptorIndex(id);\n return Boolean(this.fns[index]);\n }\n\n getInterceptorIndex(id: number | Interceptor): number {\n if (typeof id === \"number\") {\n return this.fns[id] ? id : -1;\n }\n return this.fns.indexOf(id);\n }\n\n update(\n id: number | Interceptor,\n fn: Interceptor,\n ): number | Interceptor | false {\n const index = this.getInterceptorIndex(id);\n if (this.fns[index]) {\n this.fns[index] = fn;\n return id;\n }\n return false;\n }\n\n use(fn: Interceptor): number {\n this.fns.push(fn);\n return this.fns.length - 1;\n }\n}\n\nexport interface Middleware<Req, Res, Err, Options> {\n error: Interceptors<ErrInterceptor<Err, Res, Req, Options>>;\n request: Interceptors<ReqInterceptor<Req, Options>>;\n response: Interceptors<ResInterceptor<Res, Req, Options>>;\n}\n\nexport const createInterceptors = <Req, Res, Err, Options>(): Middleware<\n Req,\n Res,\n Err,\n Options\n> => ({\n error: new Interceptors<ErrInterceptor<Err, Res, Req, Options>>(),\n request: new Interceptors<ReqInterceptor<Req, Options>>(),\n response: new Interceptors<ResInterceptor<Res, Req, Options>>(),\n});\n\nconst defaultQuerySerializer = createQuerySerializer({\n allowReserved: false,\n array: {\n explode: true,\n style: \"form\",\n },\n object: {\n explode: true,\n style: \"deepObject\",\n },\n});\n\nconst defaultHeaders = {\n \"Content-Type\": \"application/json\",\n};\n\nexport const createConfig = <T extends ClientOptions = ClientOptions>(\n override: Config<Omit<ClientOptions, keyof T> & T> = {},\n): Config<Omit<ClientOptions, keyof T> & T> => ({\n ...jsonBodySerializer,\n headers: defaultHeaders,\n parseAs: \"auto\",\n querySerializer: defaultQuerySerializer,\n ...override,\n});\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport { createSseClient } from \"../core/serverSentEvents.gen\";\nimport type { HttpMethod } from \"../core/types.gen\";\nimport { getValidRequestBody } from \"../core/utils.gen\";\nimport type {\n Client,\n Config,\n RequestOptions,\n ResolvedRequestOptions,\n} from \"./types.gen\";\nimport {\n buildUrl,\n createConfig,\n createInterceptors,\n getParseAs,\n mergeConfigs,\n mergeHeaders,\n setAuthParams,\n} from \"./utils.gen\";\n\ntype ReqInit = Omit<RequestInit, \"body\" | \"headers\"> & {\n body?: any;\n headers: ReturnType<typeof mergeHeaders>;\n};\n\nexport const createClient = (config: Config = {}): Client => {\n let _config = mergeConfigs(createConfig(), config);\n\n const getConfig = (): Config => ({ ..._config });\n\n const setConfig = (config: Config): Config => {\n _config = mergeConfigs(_config, config);\n return getConfig();\n };\n\n const interceptors = createInterceptors<\n Request,\n Response,\n unknown,\n ResolvedRequestOptions\n >();\n\n const beforeRequest = async <\n TData = unknown,\n TResponseStyle extends \"data\" | \"fields\" = \"fields\",\n ThrowOnError extends boolean = boolean,\n Url extends string = string,\n >(\n options: RequestOptions<TData, TResponseStyle, ThrowOnError, Url>,\n ) => {\n const opts = {\n ..._config,\n ...options,\n fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,\n headers: mergeHeaders(_config.headers, options.headers),\n serializedBody: undefined as string | undefined,\n };\n\n if (opts.security) {\n await setAuthParams(opts);\n }\n\n if (opts.requestValidator) {\n await opts.requestValidator(opts);\n }\n\n if (opts.body !== undefined && opts.bodySerializer) {\n opts.serializedBody = opts.bodySerializer(opts.body) as\n string | undefined;\n }\n\n // remove Content-Type header if body is empty to avoid sending invalid requests\n if (opts.body === undefined || opts.serializedBody === \"\") {\n opts.headers.delete(\"Content-Type\");\n }\n\n const resolvedOpts = opts as typeof opts &\n ResolvedRequestOptions<TResponseStyle, ThrowOnError, Url>;\n const url = buildUrl(resolvedOpts);\n\n return { opts: resolvedOpts, url };\n };\n\n const request: Client[\"request\"] = async (options) => {\n const throwOnError = options.throwOnError ?? _config.throwOnError;\n const responseStyle = options.responseStyle ?? _config.responseStyle;\n\n let request: Request | undefined;\n let response: Response | undefined;\n\n try {\n const { opts, url } = await beforeRequest(options);\n const requestInit: ReqInit = {\n redirect: \"follow\",\n ...opts,\n body: getValidRequestBody(opts),\n };\n\n request = new Request(url, requestInit);\n\n for (const fn of interceptors.request.fns) {\n if (fn) {\n request = await fn(request, opts);\n }\n }\n\n // fetch must be assigned here, otherwise it would throw the error:\n // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation\n const _fetch = opts.fetch!;\n\n response = await _fetch(request);\n\n for (const fn of interceptors.response.fns) {\n if (fn) {\n response = await fn(response, request, opts);\n }\n }\n\n const result = {\n request,\n response,\n };\n\n if (response.ok) {\n const parseAs =\n (opts.parseAs === \"auto\"\n ? getParseAs(response.headers.get(\"Content-Type\"))\n : opts.parseAs) ?? \"json\";\n\n if (\n response.status === 204 ||\n response.headers.get(\"Content-Length\") === \"0\"\n ) {\n let emptyData: any;\n switch (parseAs) {\n case \"arrayBuffer\":\n case \"blob\":\n case \"text\":\n emptyData = await response[parseAs]();\n break;\n case \"formData\":\n emptyData = new FormData();\n break;\n case \"stream\":\n emptyData = response.body;\n break;\n case \"json\":\n default:\n emptyData = {};\n break;\n }\n return opts.responseStyle === \"data\"\n ? emptyData\n : {\n data: emptyData,\n ...result,\n };\n }\n\n let data: any;\n switch (parseAs) {\n case \"arrayBuffer\":\n case \"blob\":\n case \"formData\":\n case \"text\":\n data = await response[parseAs]();\n break;\n case \"json\": {\n // Some servers return 200 with no Content-Length and empty body.\n // response.json() would throw; read as text and parse if non-empty.\n const text = await response.text();\n data = text ? JSON.parse(text) : {};\n break;\n }\n case \"stream\":\n return opts.responseStyle === \"data\"\n ? response.body\n : {\n data: response.body,\n ...result,\n };\n }\n\n if (parseAs === \"json\") {\n if (opts.responseValidator) {\n await opts.responseValidator(data);\n }\n\n if (opts.responseTransformer) {\n data = await opts.responseTransformer(data);\n }\n }\n\n return opts.responseStyle === \"data\"\n ? data\n : {\n data,\n ...result,\n };\n }\n\n const textError = await response.text();\n let jsonError: unknown;\n\n try {\n jsonError = JSON.parse(textError);\n } catch {\n // noop\n }\n\n throw jsonError ?? textError;\n } catch (error) {\n let finalError = error;\n\n for (const fn of interceptors.error.fns) {\n if (fn) {\n finalError = await fn(\n finalError,\n response,\n request,\n options as ResolvedRequestOptions,\n );\n }\n }\n\n finalError = finalError || {};\n\n if (throwOnError) {\n throw finalError;\n }\n\n // TODO: we probably want to return error and improve types\n return responseStyle === \"data\"\n ? undefined\n : {\n error: finalError,\n request,\n response,\n };\n }\n };\n\n const makeMethodFn =\n (method: Uppercase<HttpMethod>) => (options: RequestOptions) =>\n request({ ...options, method });\n\n const makeSseFn =\n (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {\n const { opts, url } = await beforeRequest(options);\n return createSseClient({\n ...opts,\n body: opts.body as BodyInit | null | undefined,\n method,\n onRequest: async (url, init) => {\n let request = new Request(url, init);\n for (const fn of interceptors.request.fns) {\n if (fn) {\n request = await fn(request, opts);\n }\n }\n return request;\n },\n serializedBody: getValidRequestBody(opts) as\n BodyInit | null | undefined,\n url,\n });\n };\n\n const _buildUrl: Client[\"buildUrl\"] = (options) =>\n buildUrl({ ..._config, ...options });\n\n return {\n buildUrl: _buildUrl,\n connect: makeMethodFn(\"CONNECT\"),\n delete: makeMethodFn(\"DELETE\"),\n get: makeMethodFn(\"GET\"),\n getConfig,\n head: makeMethodFn(\"HEAD\"),\n interceptors,\n options: makeMethodFn(\"OPTIONS\"),\n patch: makeMethodFn(\"PATCH\"),\n post: makeMethodFn(\"POST\"),\n put: makeMethodFn(\"PUT\"),\n request,\n setConfig,\n sse: {\n connect: makeSseFn(\"CONNECT\"),\n delete: makeSseFn(\"DELETE\"),\n get: makeSseFn(\"GET\"),\n head: makeSseFn(\"HEAD\"),\n options: makeSseFn(\"OPTIONS\"),\n patch: makeSseFn(\"PATCH\"),\n post: makeSseFn(\"POST\"),\n put: makeSseFn(\"PUT\"),\n trace: makeSseFn(\"TRACE\"),\n },\n trace: makeMethodFn(\"TRACE\"),\n } as Client;\n};\n","// The retry/refresh fetch wrapper passed to the generated client. Centralizes the\n// three contract-driven behaviors (plan §4.1 #6, §9):\n// - 401 -> refresh the token (rotation, via TokenManager) and retry ONCE\n// - 429 -> honor X-RateLimit-Reset (NOT Retry-After) and retry (safe: request was\n// rejected, not processed)\n// - 5xx / network error -> retry IDEMPOTENT requests only (GET/HEAD) with\n// exponential backoff + jitter. Writes are never auto-retried (no\n// universal idempotency key).\n\nimport type { TokenManager } from \"./token-manager.js\";\n\nexport interface RetryOptions {\n maxRetries?: number;\n baseDelayMs?: number;\n maxDelayMs?: number;\n}\n\nexport interface HttpDeps {\n tokenManager?: TokenManager;\n fetch?: typeof fetch;\n sleep?: (ms: number) => Promise<void>;\n now?: () => number;\n /** Deterministic jitter source for tests; defaults to Math.random. */\n random?: () => number;\n retry?: RetryOptions;\n}\n\ntype FetchInput = Parameters<typeof fetch>[0];\n\nconst IDEMPOTENT = new Set([\"GET\", \"HEAD\", \"OPTIONS\"]);\n\nfunction methodOf(input: FetchInput, init?: RequestInit): string {\n if (init?.method) return init.method.toUpperCase();\n if (input instanceof Request) return input.method.toUpperCase();\n return \"GET\";\n}\n\n/**\n * Compute how long to wait for a 429, reading X-RateLimit-Reset. The header may be\n * either an absolute epoch-seconds timestamp or a delta in seconds — handle both.\n * Bounded so a misbehaving header can't hang the caller.\n */\nexport function rateLimitWaitMs(response: Response, now: number, maxDelayMs: number): number {\n const raw = response.headers.get(\"x-ratelimit-reset\");\n if (!raw) return Math.min(1000, maxDelayMs);\n const n = Number(raw);\n if (!Number.isFinite(n)) return Math.min(1000, maxDelayMs);\n // Heuristic: values larger than ~now-in-seconds are absolute epoch timestamps.\n const wait = n > 1_000_000_000 ? n * 1000 - now : n * 1000;\n return Math.max(0, Math.min(wait, maxDelayMs));\n}\n\nfunction backoffMs(attempt: number, opts: Required<RetryOptions>, random: () => number): number {\n const exp = opts.baseDelayMs * 2 ** attempt;\n const jitter = exp * 0.5 * random();\n return Math.min(exp + jitter, opts.maxDelayMs);\n}\n\nexport function createFetch(deps: HttpDeps): typeof fetch {\n const baseFetch = deps.fetch ?? fetch;\n const sleep = deps.sleep ?? ((ms: number) => new Promise<void>((r) => setTimeout(r, ms)));\n const now = deps.now ?? Date.now;\n const random = deps.random ?? Math.random;\n const retry: Required<RetryOptions> = {\n maxRetries: deps.retry?.maxRetries ?? 2,\n baseDelayMs: deps.retry?.baseDelayMs ?? 250,\n maxDelayMs: deps.retry?.maxDelayMs ?? 60_000,\n };\n\n return async function wrappedFetch(input: FetchInput, init?: RequestInit): Promise<Response> {\n const method = methodOf(input, init);\n const idempotent = IDEMPOTENT.has(method);\n const isRequest = input instanceof Request;\n let refreshed = false;\n let attempt = 0;\n let retryToken: string | undefined; // set after a refresh, applied to the next attempt\n\n // Issue the request for one attempt. CRITICAL: a `Request` body is a single-use\n // stream — the hey-api client hands us a `Request`, and the first fetch consumes\n // it, so we must NOT re-dispatch the same object on a retry. Clone per attempt\n // (leaving `input` pristine), overriding the bearer after a refresh. For the\n // (url, init) form, a string body is freely re-sendable.\n const dispatch = (authToken?: string): Promise<Response> => {\n if (isRequest) {\n const fresh = (input as Request).clone();\n if (authToken === undefined) return baseFetch(fresh);\n const headers = new Headers(fresh.headers);\n headers.set(\"Authorization\", `Bearer ${authToken}`);\n return baseFetch(new Request(fresh, { headers }));\n }\n const nextInit =\n authToken === undefined\n ? init\n : (() => {\n const headers = new Headers(init?.headers);\n headers.set(\"Authorization\", `Bearer ${authToken}`);\n return { ...init, headers };\n })();\n return baseFetch(input, nextInit);\n };\n\n for (;;) {\n let response: Response | undefined;\n let networkError: unknown;\n try {\n response = await dispatch(retryToken);\n } catch (err) {\n networkError = err;\n }\n\n // --- 401: refresh once, then retry (any method — a 401 means the request was\n // rejected before processing, so re-sending is safe; the per-attempt clone makes\n // body-bearing writes replayable). ---\n if (response?.status === 401 && !refreshed && deps.tokenManager?.canRefresh) {\n refreshed = true;\n const next = await deps.tokenManager.refresh();\n retryToken = next.accessToken;\n continue;\n }\n\n // --- 429: honor X-RateLimit-Reset, retry (bounded) ---\n if (response?.status === 429 && attempt < retry.maxRetries) {\n attempt++;\n await sleep(rateLimitWaitMs(response, now(), retry.maxDelayMs));\n continue;\n }\n\n // --- 5xx / network: retry idempotent only ---\n const transient = networkError !== undefined || (response !== undefined && response.status >= 500);\n if (transient && idempotent && attempt < retry.maxRetries) {\n attempt++;\n await sleep(backoffMs(attempt, retry, random));\n continue;\n }\n\n if (response) return response;\n throw networkError;\n }\n };\n}\n","// OAuth 2.0 helpers. The contract review established:\n// - BOTH authorization_code + PKCE (user flows) AND client_credentials (server, read:public)\n// - refresh tokens ROTATE: every refresh returns a NEW refresh token that MUST be persisted\n//\n// HOST SPLIT: /authorize and /token live on different hosts by purpose.\n// - /token (+ refresh) is on api.wefunder.com — the edge gateway routes by the\n// credential's mode segment (form-body client_id for /oauth/token), so a pk_test_\n// grant mints in the sandbox cluster and a pk_live_ grant in live. ONE token host\n// for both modes; do NOT route by prefix here. (wefunder.com/oauth/token still works\n// as a transition alias but mints into live — wrong for sandbox once the gateway is\n// in front of the API, so we default to the gateway host.)\n// - /authorize is the browser consent redirect (needs the human session). Live consent\n// is on wefunder.com; sandbox (pk_test_) consent is on the canonical sandbox host\n// oauth.wefunder-sandbox.com. createAuthorizationUrl picks by client_id prefix.\n// All hosts remain independently overridable (authorizeBaseUrl / tokenBaseUrl).\n//\n// These helpers are framework-agnostic and depend only on Web Crypto + fetch (Node 18+).\n\nimport { createHash, randomBytes } from \"node:crypto\";\n\n/** Host for the LIVE browser /authorize redirect (pk_live_ / default). */\nexport const DEFAULT_AUTHORIZE_BASE_URL = \"https://wefunder.com/oauth\";\n\n/** Host for the SANDBOX browser /authorize redirect (pk_test_). Canonical, client_id-derivable. */\nexport const SANDBOX_AUTHORIZE_BASE_URL = \"https://oauth.wefunder-sandbox.com/oauth\";\n\n// Host for /token (+ refresh). The edge gateway routes test/live by the client_id mode,\n// so one host serves both. Callers can override via `tokenBaseUrl`.\nexport const DEFAULT_TOKEN_BASE_URL = \"https://api.wefunder.com/oauth\";\n\n/**\n * @deprecated Use `authorizeBaseUrl` / `tokenBaseUrl` instead. Kept as a convenience\n * alias that sets BOTH hosts at once. Equals the authorize default today.\n */\nexport const DEFAULT_OAUTH_BASE_URL = DEFAULT_AUTHORIZE_BASE_URL;\n\n/** Hosts can be set together (`oauthBaseUrl`) or independently. Precedence: specific > alias > default. */\nexport interface OAuthHostOptions {\n /** Overrides BOTH hosts. Prefer the specific options below. */\n oauthBaseUrl?: string;\n /** Host for the /authorize redirect. */\n authorizeBaseUrl?: string;\n /** Host for /token + refresh. */\n tokenBaseUrl?: string;\n}\n\n/** The default authorize host for a client_id: sandbox host for pk_test_, else live. */\nfunction defaultAuthorizeBase(clientId: string): string {\n return clientId.startsWith(\"pk_test_\") ? SANDBOX_AUTHORIZE_BASE_URL : DEFAULT_AUTHORIZE_BASE_URL;\n}\n\nexport function resolveTokenBase(o: OAuthHostOptions): string {\n return o.tokenBaseUrl ?? o.oauthBaseUrl ?? DEFAULT_TOKEN_BASE_URL;\n}\n\nexport interface TokenSet {\n accessToken: string;\n refreshToken?: string;\n /** Epoch milliseconds at which the access token expires (if the server told us). */\n expiresAt?: number;\n scope?: string;\n tokenType?: string;\n}\n\ninterface RawTokenResponse {\n access_token: string;\n refresh_token?: string;\n expires_in?: number;\n scope?: string;\n token_type?: string;\n}\n\nfunction toTokenSet(raw: RawTokenResponse, now: number): TokenSet {\n return {\n accessToken: raw.access_token,\n refreshToken: raw.refresh_token,\n expiresAt: raw.expires_in ? now + raw.expires_in * 1000 : undefined,\n scope: raw.scope,\n tokenType: raw.token_type,\n };\n}\n\nasync function postToken(\n oauthBaseUrl: string,\n params: Record<string, string>,\n fetchImpl: typeof fetch,\n now: () => number,\n): Promise<TokenSet> {\n const res = await fetchImpl(`${oauthBaseUrl}/token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams(params).toString(),\n });\n if (!res.ok) {\n let detail = \"\";\n try {\n detail = JSON.stringify(await res.json());\n } catch {\n detail = await res.text().catch(() => \"\");\n }\n throw new Error(`OAuth token request failed (${res.status}): ${detail}`);\n }\n return toTokenSet((await res.json()) as RawTokenResponse, now());\n}\n\n// ---- PKCE (authorization_code) ----\n\nexport interface Pkce {\n codeVerifier: string;\n codeChallenge: string;\n codeChallengeMethod: \"S256\";\n}\n\nfunction base64Url(buf: Buffer): string {\n return buf.toString(\"base64\").replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n/** Generate a PKCE verifier/challenge pair (RFC 7636, S256). */\nexport function generatePkce(): Pkce {\n const codeVerifier = base64Url(randomBytes(32));\n const codeChallenge = base64Url(createHash(\"sha256\").update(codeVerifier).digest());\n return { codeVerifier, codeChallenge, codeChallengeMethod: \"S256\" };\n}\n\nexport interface AuthorizationUrlOptions extends OAuthHostOptions {\n clientId: string;\n redirectUri: string;\n scopes: string[];\n /** Opaque CSRF token you generate and verify on callback. */\n state: string;\n pkce: Pkce;\n}\n\n/** Build the URL to redirect a user to for the authorization_code + PKCE flow. */\nexport function createAuthorizationUrl(opts: AuthorizationUrlOptions): string {\n // Explicit override wins; otherwise pick the host from the client_id mode\n // (pk_test_ → sandbox consent host, else live). The token host is separate.\n const base = opts.authorizeBaseUrl ?? opts.oauthBaseUrl ?? defaultAuthorizeBase(opts.clientId);\n const q = new URLSearchParams({\n response_type: \"code\",\n client_id: opts.clientId,\n redirect_uri: opts.redirectUri,\n scope: opts.scopes.join(\" \"),\n state: opts.state,\n code_challenge: opts.pkce.codeChallenge,\n code_challenge_method: opts.pkce.codeChallengeMethod,\n });\n return `${base}/authorize?${q.toString()}`;\n}\n\nexport interface ExchangeCodeOptions extends OAuthHostOptions {\n clientId: string;\n /** Public (PKCE) clients omit this; confidential clients pass it. */\n clientSecret?: string;\n code: string;\n redirectUri: string;\n codeVerifier: string;\n fetch?: typeof fetch;\n now?: () => number;\n}\n\n/** Exchange an authorization code (+ PKCE verifier) for a token set. */\nexport function exchangeCode(opts: ExchangeCodeOptions): Promise<TokenSet> {\n const params: Record<string, string> = {\n grant_type: \"authorization_code\",\n client_id: opts.clientId,\n code: opts.code,\n redirect_uri: opts.redirectUri,\n code_verifier: opts.codeVerifier,\n };\n if (opts.clientSecret) params.client_secret = opts.clientSecret;\n return postToken(resolveTokenBase(opts), params, opts.fetch ?? fetch, opts.now ?? Date.now);\n}\n\n// ---- client_credentials (server-to-server, read:public) ----\n\nexport interface ClientCredentialsOptions extends OAuthHostOptions {\n clientId: string;\n clientSecret: string;\n scopes?: string[];\n fetch?: typeof fetch;\n now?: () => number;\n}\n\nexport function clientCredentialsGrant(opts: ClientCredentialsOptions): Promise<TokenSet> {\n const params: Record<string, string> = {\n grant_type: \"client_credentials\",\n client_id: opts.clientId,\n client_secret: opts.clientSecret,\n };\n if (opts.scopes?.length) params.scope = opts.scopes.join(\" \");\n return postToken(resolveTokenBase(opts), params, opts.fetch ?? fetch, opts.now ?? Date.now);\n}\n\n// ---- refresh with ROTATION ----\n\nexport interface RefreshOptions extends OAuthHostOptions {\n clientId: string;\n clientSecret?: string;\n refreshToken: string;\n fetch?: typeof fetch;\n now?: () => number;\n}\n\n/**\n * Refresh an access token. CRITICAL: the returned TokenSet carries a NEW refresh\n * token (rotation). The caller MUST persist it — reusing the old refresh token\n * after rotation results in a permanent 401. The client/TokenManager handles this.\n */\nexport function refreshToken(opts: RefreshOptions): Promise<TokenSet> {\n const params: Record<string, string> = {\n grant_type: \"refresh_token\",\n client_id: opts.clientId,\n refresh_token: opts.refreshToken,\n };\n if (opts.clientSecret) params.client_secret = opts.clientSecret;\n return postToken(resolveTokenBase(opts), params, opts.fetch ?? fetch, opts.now ?? Date.now);\n}\n","// Typed errors mapped from the REAL Wefunder error envelope. Confirmed against\n// api/v2/base_controller.rb#render_error (and the doorkeeper render options):\n// { \"error\": { \"type\", \"message\", \"details\"?, \"request_id\", \"remediation\"? } }\n// NOTE: request_id and remediation are NESTED under `error` (not top-level) — the\n// spec's Error schema models neither, but the runtime always emits request_id.\n\nexport interface WefunderErrorBody {\n error?: {\n type?: string;\n message?: string;\n details?: unknown;\n request_id?: string;\n remediation?: string;\n };\n // Defensive: some envelopes (e.g. *WithMeta success meta) carry request_id here.\n request_id?: string;\n}\n\n/** Response header carrying the partner-facing request id (Stripe-style `req_…`). */\nexport const REQUEST_ID_HEADER = \"x-wf-request-id\";\n\n/** Prefer the X-Wf-Request-Id response header; fall back to a body-derived id. */\nexport function requestIdFrom(response: Response | undefined, bodyRequestId: string | undefined): string | undefined {\n return response?.headers.get(REQUEST_ID_HEADER) ?? bodyRequestId;\n}\n\nexport class WefunderError extends Error {\n readonly status: number;\n readonly type: string;\n readonly requestId?: string;\n readonly details?: unknown;\n /** Server-provided hint on how to resolve the error, when present. */\n readonly remediation?: string;\n /** Documentation pointer surfaced to developers in stack traces / logs. */\n readonly documentationUrl = \"https://docs.wefunder.com/api-reference\";\n\n constructor(args: {\n status: number;\n type: string;\n message: string;\n requestId?: string;\n details?: unknown;\n remediation?: string;\n }) {\n super(args.message);\n this.name = \"WefunderError\";\n this.status = args.status;\n this.type = args.type;\n this.requestId = args.requestId;\n this.details = args.details;\n this.remediation = args.remediation;\n }\n}\n\n/** Raised when token refresh is needed but no refresh token / refresher is configured. */\nexport class WefunderAuthError extends WefunderError {\n constructor(message: string) {\n super({ status: 401, type: \"unauthorized\", message });\n this.name = \"WefunderAuthError\";\n }\n}\n\n/**\n * Build a WefunderError from a failed Response. Reads the typed envelope from the\n * body; falls back gracefully when the body isn't the expected shape.\n */\nexport async function errorFromResponse(response: Response): Promise<WefunderError> {\n let body: WefunderErrorBody | undefined;\n try {\n body = (await response.clone().json()) as WefunderErrorBody;\n } catch {\n // non-JSON body (e.g. an HTML 502 from the edge) — keep body undefined\n }\n const err = body?.error ?? {};\n return new WefunderError({\n status: response.status,\n type: err.type ?? \"api_error\",\n message: err.message ?? response.statusText ?? \"Request failed\",\n // X-Wf-Request-Id is set on every authenticated response (base_controller.rb),\n // so it's present even when the body isn't JSON (e.g. an HTML 502 from the edge),\n // unlike the nested error.request_id. Prefer the header; fall back to the body.\n requestId: requestIdFrom(response, err.request_id ?? body?.request_id),\n details: err.details,\n remediation: err.remediation,\n });\n}\n","// Holds the live token state and owns token recovery + persistence. Two recovery\n// strategies, picked automatically:\n// - refresh_token (user flows): rotates — every refresh returns a NEW refresh\n// token, persisted BEFORE the next request can use it (the CRITICAL invariant).\n// - re-mint (client_credentials): cc tokens have NO refresh token, but a client\n// built via fromClientCredentials holds the grant inputs, so it can mint a fresh\n// token on expiry/401 instead of throwing. (Stress-test finding A.)\n// Either way, concurrent callers share one in-flight promise so a burst of 401s\n// fires a single recovery (no rotation race / thundering herd).\n\nimport {\n refreshToken,\n resolveTokenBase,\n type TokenSet,\n type OAuthHostOptions,\n} from \"./oauth.js\";\nimport { WefunderAuthError } from \"./errors.js\";\n\n/**\n * The token store failed to save a rotated token set. `tokens` is the rotated set that is NOT\n * yet durable and NOT yet in use: the manager keeps it pending and retries the save on the next\n * call (or persist it yourself and call `markPersisted()`). Until it is saved no request uses it,\n * and the consumed refresh token is never reused either.\n */\nexport class WefunderTokenPersistenceError extends Error {\n readonly tokens: TokenSet;\n constructor(tokens: TokenSet, cause: unknown) {\n super(\n `Token store failed to save the rotated token set: ${cause instanceof Error ? cause.message : String(cause)}`,\n { cause },\n );\n this.name = \"WefunderTokenPersistenceError\";\n this.tokens = tokens;\n }\n}\n\n/** Pluggable persistence for the rotating token set (DB row, secrets manager, etc.). */\nexport interface TokenStore {\n load?(): Promise<TokenSet | undefined> | TokenSet | undefined;\n save(tokens: TokenSet): Promise<void> | void;\n}\n\nexport interface TokenManagerOptions extends OAuthHostOptions {\n tokens: TokenSet;\n clientId?: string;\n clientSecret?: string;\n /**\n * For client_credentials clients: mint a fresh token from the stored grant inputs.\n * When set (and there's no refresh token), this is the recovery strategy.\n */\n reMint?: () => Promise<TokenSet>;\n /** Called with the new TokenSet on every successful recovery (rotation or re-mint). */\n onTokenRefresh?: (tokens: TokenSet) => void | Promise<void>;\n store?: TokenStore;\n fetch?: typeof fetch;\n now?: () => number;\n /** Refresh proactively when the access token is within this many ms of expiry. */\n expiryLeewayMs?: number;\n}\n\nfunction sameTokenSet(a: TokenSet, b: TokenSet): boolean {\n return a.accessToken === b.accessToken && a.refreshToken === b.refreshToken;\n}\n\nexport class TokenManager {\n #tokens: TokenSet;\n readonly #clientId?: string;\n readonly #clientSecret?: string;\n readonly #reMint?: () => Promise<TokenSet>;\n readonly #tokenBaseUrl: string;\n readonly #onTokenRefresh?: (tokens: TokenSet) => void | Promise<void>;\n readonly #store?: TokenStore;\n readonly #fetch: typeof fetch;\n readonly #now: () => number;\n readonly #leeway: number;\n #inflight: Promise<TokenSet> | undefined;\n #pending: TokenSet | undefined;\n\n constructor(opts: TokenManagerOptions) {\n this.#tokens = opts.tokens;\n this.#clientId = opts.clientId;\n this.#clientSecret = opts.clientSecret;\n this.#reMint = opts.reMint;\n this.#tokenBaseUrl = resolveTokenBase(opts);\n this.#onTokenRefresh = opts.onTokenRefresh;\n this.#store = opts.store;\n this.#fetch = opts.fetch ?? fetch;\n this.#now = opts.now ?? Date.now;\n this.#leeway = opts.expiryLeewayMs ?? 30_000;\n }\n\n /** The durable, in-use token set. A rotated set that could not be persisted sits in `pendingTokens`. */\n get current(): TokenSet {\n return this.#tokens;\n }\n\n /** True if the manager can recover an expired token (rotate a refresh token or re-mint). */\n get canRefresh(): boolean {\n return Boolean(\n (this.#tokens.refreshToken && this.#clientId) || this.#reMint,\n );\n }\n\n /** A rotated set awaiting a successful `store.save` (see `WefunderTokenPersistenceError`). */\n get pendingTokens(): TokenSet | undefined {\n return this.#pending;\n }\n\n /**\n * Tell the manager you persisted `tokens` (the set from a `WefunderTokenPersistenceError`)\n * yourself. Publishes it only if it is still the pending set — a stale acknowledgment (the\n * manager has since rotated again) is a no-op and returns false, so an older save can never\n * publish a newer, unsaved set.\n */\n async markPersisted(tokens: TokenSet): Promise<boolean> {\n const pending = this.#pending;\n if (!pending || !sameTokenSet(pending, tokens)) return false;\n this.#pending = undefined;\n this.#tokens = pending;\n return true;\n }\n\n /**\n * Returns a valid access token, refreshing proactively if it's expired/near-expiry. If a\n * rotated set is pending persistence, the save is retried first — no request uses an\n * undurable token.\n */\n async getAccessToken(): Promise<string> {\n if (this.#pending) await this.refresh();\n const { expiresAt } = this.#tokens;\n if (\n expiresAt !== undefined &&\n this.#now() >= expiresAt - this.#leeway &&\n this.canRefresh\n ) {\n await this.refresh();\n }\n return this.#tokens.accessToken;\n }\n\n /**\n * Recover an expired/rejected token (e.g. after a 401): rotates the refresh token\n * if there is one, otherwise re-mints (client_credentials). Coalesces concurrent\n * calls into one network round-trip, then persists. Returns the new token set.\n */\n async refresh(): Promise<TokenSet> {\n if (this.#inflight) return this.#inflight;\n // A rotated set awaiting persistence: retry the save rather than rotating again (the old\n // refresh token was consumed by that rotation).\n if (this.#pending) {\n this.#inflight = this.#publishPending();\n try {\n return await this.#inflight;\n } finally {\n this.#inflight = undefined;\n }\n }\n const strategy = this.#recoveryStrategy();\n if (!strategy) {\n throw new WefunderAuthError(\n \"Access token expired and no refresh token / re-mint capability is configured.\",\n );\n }\n this.#inflight = (async () => {\n this.#pending = await strategy();\n return this.#publishPending();\n })();\n try {\n return await this.#inflight;\n } finally {\n this.#inflight = undefined;\n }\n }\n\n // Persist BEFORE publishing: no caller may use the rotated token until it is durable, and a\n // failed save must not leave the process working in memory but unable to reconnect after a\n // restart. On failure the set stays pending and WefunderTokenPersistenceError is thrown; the\n // next call retries the save.\n async #publishPending(): Promise<TokenSet> {\n const tokens = this.#pending!;\n try {\n await this.#store?.save(tokens);\n // `onTokenRefresh` is a persistence path too (the OAuth example persists there), so it\n // runs BEFORE publication and a failure keeps the set pending exactly like a store failure.\n await this.#onTokenRefresh?.(tokens);\n } catch (err) {\n throw new WefunderTokenPersistenceError(tokens, err);\n }\n this.#pending = undefined;\n this.#tokens = tokens;\n return tokens;\n }\n\n // Pick the recovery strategy: refresh_token rotation, else cc re-mint, else none.\n #recoveryStrategy(): (() => Promise<TokenSet>) | undefined {\n const refreshTokenValue = this.#tokens.refreshToken;\n if (refreshTokenValue && this.#clientId) {\n const clientId = this.#clientId;\n return async () => {\n const next = await refreshToken({\n clientId,\n clientSecret: this.#clientSecret,\n refreshToken: refreshTokenValue,\n tokenBaseUrl: this.#tokenBaseUrl,\n fetch: this.#fetch,\n now: this.#now,\n });\n // Some servers omit a fresh refresh_token on rotation-disabled flows;\n // keep the previous one rather than dropping our ability to refresh.\n if (!next.refreshToken) next.refreshToken = refreshTokenValue;\n return next;\n };\n }\n return this.#reMint;\n }\n}\n","// Lazy auto-pagination. The cursor is treated as an OPAQUE token (plan §4.1 #5):\n// different endpoints back it with an int id, an ISO timestamp, or an offset, so we\n// never inspect or arithmetic it — we just feed `meta.next_cursor` back verbatim.\n// Streams items one page at a time (never buffers the whole result set).\n\nexport type Cursor = string | number;\n\nexport interface Page<T> {\n data?: T[] | null;\n meta?: {\n has_more?: boolean;\n next_cursor?: Cursor | null;\n [k: string]: unknown;\n };\n}\n\n/** Fetches a single page given an opaque cursor (undefined = first page). */\nexport type PageFetcher<T> = (cursor?: Cursor) => Promise<Page<T>>;\n\n/** Yields every item across all pages, lazily. */\nexport async function* paginate<T>(fetchPage: PageFetcher<T>): AsyncGenerator<T> {\n let cursor: Cursor | undefined;\n const seen = new Set<Cursor>();\n for (;;) {\n const page = await fetchPage(cursor);\n for (const item of page.data ?? []) yield item;\n\n const meta = page.meta ?? {};\n const next = meta.next_cursor;\n // Stop conditions: explicit has_more=false, no next cursor, or a cursor that\n // doesn't advance (defensive guard against an endpoint that loops).\n if (meta.has_more === false) return;\n if (next === undefined || next === null) return;\n if (seen.has(next)) return;\n seen.add(next);\n cursor = next;\n }\n}\n\n/** Collect all items into an array. Convenience over `paginate` for small result sets. */\nexport async function collect<T>(fetchPage: PageFetcher<T>): Promise<T[]> {\n const out: T[] = [];\n for await (const item of paginate(fetchPage)) out.push(item);\n return out;\n}\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type {\n Client,\n ClientMeta,\n Options as Options2,\n RequestResult,\n TDataShape,\n} from \"./client\";\nimport { client } from \"./client.gen\";\nimport type {\n ApproveSyndicateMemberData,\n ApproveSyndicateMemberErrors,\n ApproveSyndicateMemberResponses,\n CloseSyndicateDealData,\n CloseSyndicateDealErrors,\n CloseSyndicateDealResponses,\n CreateInstallationData,\n CreateInstallationErrors,\n CreateInstallationResponses,\n CreateInstallationTokenData,\n CreateInstallationTokenErrors,\n CreateInstallationTokenResponses,\n CreateIntentData,\n CreateIntentErrors,\n CreateIntentResponses,\n CreatePartnerInviteData,\n CreatePartnerInviteErrors,\n CreatePartnerInviteResponses,\n CreateWebhookEndpointData,\n CreateWebhookEndpointErrors,\n CreateWebhookEndpointResponses,\n CreateWebhookSubscriptionData,\n CreateWebhookSubscriptionErrors,\n CreateWebhookSubscriptionResponses,\n DeleteWebhookEndpointData,\n DeleteWebhookEndpointErrors,\n DeleteWebhookEndpointResponses,\n DeleteWebhookSubscriptionData,\n DeleteWebhookSubscriptionErrors,\n DeleteWebhookSubscriptionResponses,\n DemoteSyndicateMemberData,\n DemoteSyndicateMemberErrors,\n DemoteSyndicateMemberResponses,\n ExportSyndicateMembersCsvData,\n ExportSyndicateMembersCsvErrors,\n ExportSyndicateMembersCsvResponses,\n FinalizeSyndicateDealData,\n FinalizeSyndicateDealErrors,\n FinalizeSyndicateDealResponses,\n FollowCompanyData,\n FollowCompanyErrors,\n FollowCompanyResponses,\n GetAttributionMeData,\n GetAttributionMeErrors,\n GetAttributionMeResponses,\n GetAttributionStatsData,\n GetAttributionStatsErrors,\n GetAttributionStatsResponses,\n GetCompanyData,\n GetCompanyDisclosuresData,\n GetCompanyDisclosuresErrors,\n GetCompanyDisclosuresResponses,\n GetCompanyErrors,\n GetCompanyPitchData,\n GetCompanyPitchErrors,\n GetCompanyPitchResponses,\n GetCompanyResponses,\n GetCompanyUpdateData,\n GetCompanyUpdateErrors,\n GetCompanyUpdateResponses,\n GetCurrentUserData,\n GetCurrentUserErrors,\n GetCurrentUserResponses,\n GetInstallationData,\n GetInstallationErrors,\n GetInstallationResponses,\n GetIntentData,\n GetIntentErrors,\n GetIntentResponses,\n GetInvestmentData,\n GetInvestmentErrors,\n GetInvestmentResponses,\n GetOfferingData,\n GetOfferingErrors,\n GetOfferingResponses,\n GetOfferingStatsData,\n GetOfferingStatsErrors,\n GetOfferingStatsResponses,\n GetPortfolioData,\n GetPortfolioErrors,\n GetPortfolioResponses,\n GetSyndicateData,\n GetSyndicateDealData,\n GetSyndicateDealErrors,\n GetSyndicateDealResponses,\n GetSyndicateErrors,\n GetSyndicatePortfolioData,\n GetSyndicatePortfolioErrors,\n GetSyndicatePortfolioResponses,\n GetSyndicateResponses,\n GetSyndicateStatisticsData,\n GetSyndicateStatisticsErrors,\n GetSyndicateStatisticsResponses,\n GetWebhookEndpointData,\n GetWebhookEndpointErrors,\n GetWebhookEndpointResponses,\n GetWebhookSubscriptionData,\n GetWebhookSubscriptionErrors,\n GetWebhookSubscriptionResponses,\n HideSyndicateMemberData,\n HideSyndicateMemberErrors,\n HideSyndicateMemberResponses,\n InviteSyndicateMemberData,\n InviteSyndicateMemberErrors,\n InviteSyndicateMemberResponses,\n ListActivityData,\n ListActivityErrors,\n ListActivityResponses,\n ListAttributedInvestmentsData,\n ListAttributedInvestmentsErrors,\n ListAttributedInvestmentsResponses,\n ListAttributionCampaignsData,\n ListAttributionCampaignsErrors,\n ListAttributionCampaignsResponses,\n ListCampaignsData,\n ListCampaignsErrors,\n ListCampaignsResponses,\n ListCompanyInvestmentChangesData,\n ListCompanyInvestmentChangesErrors,\n ListCompanyInvestmentChangesResponses,\n ListCompanyQuestionsData,\n ListCompanyQuestionsErrors,\n ListCompanyQuestionsResponses,\n ListCompanyUpdatesData,\n ListCompanyUpdatesErrors,\n ListCompanyUpdatesResponses,\n ListConnectedAppsData,\n ListConnectedAppsErrors,\n ListConnectedAppsResponses,\n ListEligibleInstallTargetsData,\n ListEligibleInstallTargetsErrors,\n ListEligibleInstallTargetsResponses,\n ListFollowedCompaniesData,\n ListFollowedCompaniesErrors,\n ListFollowedCompaniesResponses,\n ListInstallationsData,\n ListInstallationsErrors,\n ListInstallationsResponses,\n ListIntentsData,\n ListIntentsErrors,\n ListIntentsResponses,\n ListInvestmentsData,\n ListInvestmentsErrors,\n ListInvestmentsResponses,\n ListMyCompaniesData,\n ListMyCompaniesErrors,\n ListMyCompaniesResponses,\n ListOfferingsData,\n ListOfferingsErrors,\n ListOfferingsResponses,\n ListPartnerInvitesData,\n ListPartnerInvitesErrors,\n ListPartnerInvitesResponses,\n ListPortfolioPositionsData,\n ListPortfolioPositionsErrors,\n ListPortfolioPositionsResponses,\n ListSyndicateDealInvestorsData,\n ListSyndicateDealInvestorsErrors,\n ListSyndicateDealInvestorsResponses,\n ListSyndicateDealsData,\n ListSyndicateDealsErrors,\n ListSyndicateDealsResponses,\n ListSyndicateMemberInvestmentsData,\n ListSyndicateMemberInvestmentsErrors,\n ListSyndicateMemberInvestmentsResponses,\n ListSyndicateMembersData,\n ListSyndicateMembersErrors,\n ListSyndicateMembersResponses,\n ListSyndicatePortfolioPositionsData,\n ListSyndicatePortfolioPositionsErrors,\n ListSyndicatePortfolioPositionsResponses,\n ListSyndicatesData,\n ListSyndicatesErrors,\n ListSyndicatesResponses,\n ListWebhookEndpointsData,\n ListWebhookEndpointsErrors,\n ListWebhookEndpointsResponses,\n ListWebhookSubscriptionsData,\n ListWebhookSubscriptionsErrors,\n ListWebhookSubscriptionsResponses,\n PreviewIntentData,\n PreviewIntentErrors,\n PreviewIntentResponses,\n PromoteSyndicateMemberData,\n PromoteSyndicateMemberErrors,\n PromoteSyndicateMemberResponses,\n ReactivateWebhookSubscriptionData,\n ReactivateWebhookSubscriptionErrors,\n ReactivateWebhookSubscriptionResponses,\n ReenableWebhookEndpointData,\n ReenableWebhookEndpointErrors,\n ReenableWebhookEndpointResponses,\n RegenerateWebhookSecretData,\n RegenerateWebhookSecretErrors,\n RegenerateWebhookSecretResponses,\n RegisterAsPartnerData,\n RegisterAsPartnerErrors,\n RegisterAsPartnerResponses,\n RemoveSyndicateMemberData,\n RemoveSyndicateMemberErrors,\n ReorderSyndicateMembersData,\n ReorderSyndicateMembersErrors,\n ReorderSyndicateMembersResponses,\n ResendSyndicateInviteData,\n ResendSyndicateInviteErrors,\n ResendSyndicateInviteResponses,\n RestoreSyndicateMemberData,\n RestoreSyndicateMemberErrors,\n RestoreSyndicateMemberResponses,\n RevokeConnectedAppData,\n RevokeConnectedAppErrors,\n RevokeConnectedAppResponses,\n RevokeInstallationData,\n RevokeInstallationErrors,\n RevokeInstallationResponses,\n RevokePartnerInviteData,\n RevokePartnerInviteErrors,\n RevokePartnerInviteResponses,\n RotateWebhookEndpointSecretData,\n RotateWebhookEndpointSecretErrors,\n RotateWebhookEndpointSecretResponses,\n SearchCompaniesData,\n SearchCompaniesErrors,\n SearchCompaniesResponses,\n TestWebhookEndpointData,\n TestWebhookEndpointErrors,\n TestWebhookEndpointResponses,\n TestWebhookSubscriptionData,\n TestWebhookSubscriptionErrors,\n TestWebhookSubscriptionResponses,\n UnfollowCompanyData,\n UnfollowCompanyErrors,\n UnfollowCompanyResponses,\n UpdateSyndicateData,\n UpdateSyndicateErrors,\n UpdateSyndicateMemberData,\n UpdateSyndicateMemberErrors,\n UpdateSyndicateMemberResponses,\n UpdateSyndicateResponses,\n UpdateWebhookEndpointData,\n UpdateWebhookEndpointErrors,\n UpdateWebhookEndpointResponses,\n} from \"./types.gen\";\n\nexport type Options<\n TData extends TDataShape = TDataShape,\n ThrowOnError extends boolean = boolean,\n TResponse = unknown,\n> = Options2<TData, ThrowOnError, TResponse> & {\n /**\n * You can provide a client instance returned by `createClient()` instead of\n * individual options. This might be also useful if you want to implement a\n * custom client.\n */\n client?: Client;\n /**\n * You can pass arbitrary values through the `meta` object. This can be\n * used to access values that aren't defined as part of the SDK function.\n */\n meta?: keyof ClientMeta extends never ? Record<string, unknown> : ClientMeta;\n};\n\n/**\n * List public offerings\n *\n * Returns the offerings shown on wefunder.com/explore — the curated set of companies that\n * meet Wefunder's discoverability bar (a soft-confirmed traction threshold plus approval),\n * **one offering per company**. An \"offering\" is a fundraise, addressed by its id\n * (`ofr_...`).\n *\n * **Public view (`read:public`).** Reachable with either a server-side (client_credentials)\n * token or a user access token. Private rounds (e.g. Reg D 506(b)) are never listed, and\n * low-traction or unapproved companies are excluded — exactly as they are on the website\n * for a logged-out visitor.\n *\n * **Logged-in view (`read:explore`).** A user access token carrying `read:explore` gets\n * what *that user* sees on wefunder.com/explore: the public offerings plus any the user\n * qualifies for (accredited-only / Vault deals, invited private rounds), each checked\n * against the same visibility policy the website applies. The response is a strict\n * superset of the public one — same fields and ids — with two extra attributes,\n * `publicly_visible` and `invested`, and `meta.personalized: true`. A server-side key can\n * never hold `read:explore`; a token with `read:explore` but no resolvable user gets the\n * public view.\n *\n * Order with `sort` (default: most raised); paginate with `cursor`. `meta.total_count` is\n * the number of offerings across all pages, after filters.\n *\n * **Filters** are objective, per-offering terms — exemption family, security type,\n * TTW vs. live, minimum investment ceiling, close date, amount raised floor. The response\n * echoes the applied set in `meta.filters`. An out-of-vocabulary value is a `400` naming\n * the accepted values. There are deliberately no relevance, quality, or ranking criteria.\n *\n * Use this endpoint to:\n * - Discover and monitor active deals\n * - Build deal aggregators and public listings\n *\n */\nexport const listOfferings = <ThrowOnError extends boolean = false>(\n options?: Options<ListOfferingsData, ThrowOnError>,\n): RequestResult<ListOfferingsResponses, ListOfferingsErrors, ThrowOnError> =>\n (options?.client ?? client).get<\n ListOfferingsResponses,\n ListOfferingsErrors,\n ThrowOnError\n >({\n querySerializer: {\n parameters: {\n industry: { array: { explode: false } },\n business_model: { array: { explode: false } },\n },\n },\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/explore\",\n ...options,\n });\n\n/**\n * Get a public offering\n *\n * Retrieves a single offering by its id (`ofr_...`).\n *\n * With `read:public`, a valid id for a non-public offering (e.g. a private Reg D 506(b)\n * round) returns `404` — having an id does not make an offering publicly resolvable. With\n * `read:explore` on a user access token, the offering resolves if *that user* may see it on\n * wefunder.com (e.g. an accredited-only or invited round), and the response gains\n * `publicly_visible` and `invested`.\n *\n */\nexport const getOffering = <ThrowOnError extends boolean = false>(\n options: Options<GetOfferingData, ThrowOnError>,\n): RequestResult<GetOfferingResponses, GetOfferingErrors, ThrowOnError> =>\n (options.client ?? client).get<\n GetOfferingResponses,\n GetOfferingErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/offerings/{external_id}\",\n ...options,\n });\n\n/**\n * Get a company's public Form C disclosures\n *\n * The Details tab of the company's Wefunder page as structured data — the company's own\n * Form C disclosures, section for section: financial statements for the fiscal years on\n * file, the page's ratios, the founder's current-position disclosure (cash on hand, monthly\n * revenue / costs / burn), the financial-condition narrative, document links, risks, use of\n * funds, directors and officers, 20%+ holders, capital structure, prior offerings, outstanding\n * notes and debts, and related-party transactions.\n *\n * Same \"who has a page\" rule as `GET /companies/{id}`. The round read is the page's own: the\n * display round for the viewer, swapped for its concurrent Reg CF sibling on a Reg D round,\n * and only when it is a Reg CF / ECSP round with a Form C. A company with no such round has\n * no details tab on the site and answers `404` with `error.type: no_disclosures` — distinct\n * from an unknown or hidden company. A section the company hides on the site is `null`.\n *\n * Money is USD as decimal strings; ratios are percentages as decimal strings. Everything here\n * is the issuer's own disclosure, served as filed, not a Wefunder assessment.\n *\n */\nexport const getCompanyDisclosures = <ThrowOnError extends boolean = false>(\n options: Options<GetCompanyDisclosuresData, ThrowOnError>,\n): RequestResult<\n GetCompanyDisclosuresResponses,\n GetCompanyDisclosuresErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n GetCompanyDisclosuresResponses,\n GetCompanyDisclosuresErrors,\n ThrowOnError\n >({\n querySerializer: {\n parameters: { sections: { array: { explode: false } } },\n },\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/companies/{id}/disclosures\",\n ...options,\n });\n\n/**\n * Get a company's pitch\n *\n * The Overview tab's pitch as structured data: the story as ordered blocks (`heading`,\n * `paragraph`, `list`, `image`, `video`, `footnote`), plus the perk tiers of the round the page\n * shows the viewer. Images and embedded videos keep their place in the document with an absolute\n * URL, because founders publish perk tiers, stretch goals, timelines, and charts as pictures\n * (typically with no alt text) and a plain-text rendering would drop them.\n *\n * What is parsed is what the page renders: the story passes through the site's own sanitizer\n * first, so an embed the page refuses (a host off its allowlist, a `javascript:` URL) is never\n * served here either. Same \"who has a page\" rule and round chooser as `GET /companies/{id}`.\n * A site-public company with no round the viewer may see still has a pitch (`perks: null`).\n * `perks.described_in_pitch` is a heuristic: true when the structured perk list is a placeholder\n * (\"See investor overview page\", or one identical sentence on every tier) and the real tiers are\n * in the story's images.\n *\n * `authored_by` says who wrote the story: `company` (the issuer's own words and imagery, not a\n * Wefunder assessment) or `wefunder` (a Wefunder-prepared deal memo the company did not\n * participate in; `disclaimer` carries the page's notice). A pitch can run to ~70 KB; use\n * `sections` to ask for less.\n *\n */\nexport const getCompanyPitch = <ThrowOnError extends boolean = false>(\n options: Options<GetCompanyPitchData, ThrowOnError>,\n): RequestResult<\n GetCompanyPitchResponses,\n GetCompanyPitchErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n GetCompanyPitchResponses,\n GetCompanyPitchErrors,\n ThrowOnError\n >({\n querySerializer: {\n parameters: { sections: { array: { explode: false } } },\n },\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/companies/{id}/pitch\",\n ...options,\n });\n\n/**\n * List a company's posts\n *\n * The company page's Posts tab as data: the published updates, notes, and spotlights the\n * viewer may see, pinned first then newest, with a plain-text excerpt each. With\n * `read:explore` the viewer is the authorizing user, so a follower or investor sees the\n * community- and investors-only posts the site shows them; with `read:public` it is the\n * anonymous view. Same query as the tab (`FeedItem.viewable_by`); investments, Q&A threads,\n * and investor quotes belong to other tabs and are not here. Fetch one post in full with\n * `GET /companies/{id}/updates/{update_id}`. Posts are the issuer's own words.\n *\n */\nexport const listCompanyUpdates = <ThrowOnError extends boolean = false>(\n options: Options<ListCompanyUpdatesData, ThrowOnError>,\n): RequestResult<\n ListCompanyUpdatesResponses,\n ListCompanyUpdatesErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n ListCompanyUpdatesResponses,\n ListCompanyUpdatesErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/companies/{id}/updates\",\n ...options,\n });\n\n/**\n * Get one company post in full\n *\n * One post with its full plain-text content, by the id the list returned. Same visibility as the list; a post the tab would not show this viewer is a 404.\n */\nexport const getCompanyUpdate = <ThrowOnError extends boolean = false>(\n options: Options<GetCompanyUpdateData, ThrowOnError>,\n): RequestResult<\n GetCompanyUpdateResponses,\n GetCompanyUpdateErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n GetCompanyUpdateResponses,\n GetCompanyUpdateErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/companies/{id}/updates/{update_id}\",\n ...options,\n });\n\n/**\n * List a company's investor questions and answers\n *\n * The company page's Ask tab as data: the questions investors asked and the answers, as the\n * tab lists them for this viewer (the same repository and visibility as the site). Like the tab,\n * questions default to the current raise — those asked since it opened (`meta.questions_since`);\n * `past_raises=true` includes every raise, which the site offers to any visitor because\n * past-raise questions are public. `sort` is the tab's dropdown: `relevance` (default:\n * highlighted, then answered, then most liked), `recent`, `upvoted`, `unanswered`. Text is plain.\n * Questions and answers carry their id (`cmt_...`); the integer key never leaves the API.\n * Answers are the founders' own words.\n *\n * `q` searches question and answer text (Postgres full text: quoted phrases and `-word` work;\n * one- or two-word queries also prefix-match) and replaces the sort with match rank —\n * `meta.sort` is then `search` and each result's `match` says whether its question or an\n * answer matched. `unanswered_by_team=true` keeps only questions with no live answer from the\n * company's team (the founder's queue; the `unanswered` sort merely orders by whether anyone\n * replied).\n *\n */\nexport const listCompanyQuestions = <ThrowOnError extends boolean = false>(\n options: Options<ListCompanyQuestionsData, ThrowOnError>,\n): RequestResult<\n ListCompanyQuestionsResponses,\n ListCompanyQuestionsErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n ListCompanyQuestionsResponses,\n ListCompanyQuestionsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/companies/{id}/questions\",\n ...options,\n });\n\n/**\n * Search companies by name\n *\n * The wefunder.com search bar, companies only. Same Algolia request, same result ordering,\n * and same page size as the site's top bar, so the results are what a visitor typing the\n * same text would see, in that order — companies raising now and companies funded in the\n * past, whether or not they appear on `/explore`. The order is the site's search order\n * (match quality first, then the site's tie-breaks); nothing here recommends.\n *\n * Each result carries the company's `co_` id for `GET /companies/{id}`. With `read:explore`\n * the accreditation gate matches the authorizing user (an accredited viewer sees the\n * accredited-only companies the site would show them); with `read:public` it is the\n * anonymous view.\n *\n */\nexport const searchCompanies = <ThrowOnError extends boolean = false>(\n options: Options<SearchCompaniesData, ThrowOnError>,\n): RequestResult<\n SearchCompaniesResponses,\n SearchCompaniesErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n SearchCompaniesResponses,\n SearchCompaniesErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/companies/search\",\n ...options,\n });\n\n/**\n * Get a company page\n *\n * The company page behind an offering, as structured data — the \"click a company\" step after\n * `/explore`. Addressed by the `co_...` id every offering carries in `company.id`.\n *\n * Keeps apart the three raised numbers the page shows and readers conflate:\n * `current_raise.amount_raised` (this campaign's live rounds combined, on Wefunder),\n * `past_rounds[]` (prior rounds the page lists, each tagged `source: wefunder` for rounds\n * observed here or `reported` for founder-disclosed off-platform rounds), and\n * `totals.profile_total_raised` (the number on the page's ticker bar). Every figure comes\n * from the same policy the page uses, so the API never disagrees with the site.\n *\n * **Who has a page.** Every company whose profile wefunder.com lists publicly — the same set\n * the site's search bar returns (published, not invite-only, searchable or with a live Form C;\n * accredited-only companies need an accredited viewer) — plus the `/explore` set. A funded\n * company, or one the viewer may see no round of, renders with `raising: false` and\n * `current_raise: null`; its history is in `wefunder_rounds`. **Logged-in view\n * (`read:explore`)** additionally covers the vault / syndicate-led companies the site shows an\n * accredited viewer, and the round described is the one the page would show that viewer. A\n * valid id for a company outside the viewer's set is a `404`, never a partial payload.\n *\n */\nexport const getCompany = <ThrowOnError extends boolean = false>(\n options: Options<GetCompanyData, ThrowOnError>,\n): RequestResult<GetCompanyResponses, GetCompanyErrors, ThrowOnError> =>\n (options.client ?? client).get<\n GetCompanyResponses,\n GetCompanyErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/companies/{id}\",\n ...options,\n });\n\n/**\n * Get current user profile\n *\n * Retrieves the profile information for the currently authenticated user. This endpoint returns\n * basic user details including name, email, and account status.\n *\n * Use this endpoint to:\n * - Display user information in your application\n * - Verify the identity of the authenticated user\n * - Check user account status and permissions\n *\n * The response includes the user's unique ID which can be used to reference the user in other API calls.\n *\n */\nexport const getCurrentUser = <ThrowOnError extends boolean = false>(\n options?: Options<GetCurrentUserData, ThrowOnError>,\n): RequestResult<GetCurrentUserResponses, GetCurrentUserErrors, ThrowOnError> =>\n (options?.client ?? client).get<\n GetCurrentUserResponses,\n GetCurrentUserErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/users/me\",\n ...options,\n });\n\n/**\n * List the companies you edit\n *\n * The companies the authenticated user is a founder or team member of — precisely the\n * companies the founder-scoped endpoints under `/companies/{company_id}/...` (dashboard,\n * investors, fundraises) will accept. Anyone else's company returns 403 there, so call this\n * first to learn which `co_` ids you hold. Not paginated.\n *\n * `raising` is true when the company has a round currently accepting investments or\n * reservations. `roles` are the user's roles on the company (`founder`, `employee`, ...).\n *\n */\nexport const listMyCompanies = <ThrowOnError extends boolean = false>(\n options?: Options<ListMyCompaniesData, ThrowOnError>,\n): RequestResult<\n ListMyCompaniesResponses,\n ListMyCompaniesErrors,\n ThrowOnError\n> =>\n (options?.client ?? client).get<\n ListMyCompaniesResponses,\n ListMyCompaniesErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/users/me/companies\",\n ...options,\n });\n\n/**\n * List the companies you follow\n *\n * The authenticated user's watchlist — the companies they follow on wefunder.com (the same\n * rows the site's Follow button writes), newest first. Each entry is in the search-result\n * shape (`co_` id, name, tagline, URL, logo, `raising`, `profile_available`) plus\n * `followed_at`. The list owner sees every company they follow.\n *\n */\nexport const listFollowedCompanies = <ThrowOnError extends boolean = false>(\n options?: Options<ListFollowedCompaniesData, ThrowOnError>,\n): RequestResult<\n ListFollowedCompaniesResponses,\n ListFollowedCompaniesErrors,\n ThrowOnError\n> =>\n (options?.client ?? client).get<\n ListFollowedCompaniesResponses,\n ListFollowedCompaniesErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/users/me/follows\",\n ...options,\n });\n\n/**\n * Unfollow a company\n *\n * Unfollow the company for the authenticated user. Idempotent (`changed` is false when they were not following it). No visibility gate: a follow you hold is always undoable, even for a company since hidden. Requires `write:follows`.\n */\nexport const unfollowCompany = <ThrowOnError extends boolean = false>(\n options: Options<UnfollowCompanyData, ThrowOnError>,\n): RequestResult<\n UnfollowCompanyResponses,\n UnfollowCompanyErrors,\n ThrowOnError\n> =>\n (options.client ?? client).delete<\n UnfollowCompanyResponses,\n UnfollowCompanyErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/users/me/follows/{company_id}\",\n ...options,\n });\n\n/**\n * Follow a company\n *\n * Follow the company for the authenticated user — exactly what pressing Follow on its\n * Wefunder page does, side effects included (the company counts the user as a follower and\n * may be notified; the user receives the company's updates). Idempotent: following an\n * already-followed company returns `changed: false`. `404` for a company the site would not\n * show this user. Requires `write:follows`, which the user grants explicitly; it is never\n * implied by `read:mcp`.\n *\n */\nexport const followCompany = <ThrowOnError extends boolean = false>(\n options: Options<FollowCompanyData, ThrowOnError>,\n): RequestResult<FollowCompanyResponses, FollowCompanyErrors, ThrowOnError> =>\n (options.client ?? client).put<\n FollowCompanyResponses,\n FollowCompanyErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/users/me/follows/{company_id}\",\n ...options,\n });\n\n/**\n * List or sync investments\n *\n * The investment records the token may see, served from **published** state\n * (docs: *Investments: list, sync, retrieve*). The audience is the union of the companies\n * the token's user edits (their founder-visible records) and the user's own investments\n * (every applied record of theirs, whatever its status). Filters narrow within that\n * audience; they never widen it.\n *\n * Three ways to call it:\n * - **List** (no `cursor`, no `updated_since`): the current records, tombstones excluded,\n * ordered by investment. Page with `meta.next_cursor` while `meta.has_more`; the final\n * page's cursor is a sync cursor positioned at the moment the listing started.\n * - **Sync by cursor**: only the records whose published state changed since the cursor,\n * one record per investment, tombstones (`visible: false`, only `id`) included. Apply in\n * `cursor` order; always store `meta.next_cursor`.\n * - **Sync by time**: `updated_since=<ISO 8601>` is sugar for a cursor at the ledger position\n * just before that time (with a 60 s safety margin). The response is a normal sync page,\n * so continue with its `meta.next_cursor`.\n *\n * Records are eventually consistent (about ten minutes on the common paths); each carries\n * `observed_at`. `GET /investments/{id}` returns the same shape derived now. Investor\n * identity fields on other investors' records require `read:investors:pii`; a user always\n * sees their own. Money is integer minor units plus `amounts.currency`.\n *\n * **410 Gone** means the cursor or `updated_since` predates the 90-day retention window:\n * list again and replace your dataset. `status` cannot be combined with sync (a record\n * leaving the status would never be delivered).\n *\n */\nexport const listInvestments = <ThrowOnError extends boolean = false>(\n options?: Options<ListInvestmentsData, ThrowOnError>,\n): RequestResult<\n ListInvestmentsResponses,\n ListInvestmentsErrors,\n ThrowOnError\n> =>\n (options?.client ?? client).get<\n ListInvestmentsResponses,\n ListInvestmentsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/investments\",\n ...options,\n });\n\n/**\n * Retrieve an investment (current)\n *\n * The same record shape as the list, derived **now** from the investment rather than read\n * from published state, so an investor who just acted sees the change at once. Available\n * for any investment in the token's audience: the user's own (any status) or a\n * founder-visible investment on a company the user edits. `meta.published_matches` says\n * whether the published record already agrees; the sync stream converges within its\n * interval.\n *\n */\nexport const getInvestment = <ThrowOnError extends boolean = false>(\n options: Options<GetInvestmentData, ThrowOnError>,\n): RequestResult<GetInvestmentResponses, GetInvestmentErrors, ThrowOnError> =>\n (options.client ?? client).get<\n GetInvestmentResponses,\n GetInvestmentErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/investments/{id}\",\n ...options,\n });\n\n/**\n * Investment totals for an offering\n *\n * Count and committed amount of the founder-visible published records for one offering,\n * by status, from the same rows `GET /investments?offering_id=…` lists, so the two\n * reconcile. These are **not** the public campaign figures (the progress bar has its own\n * rules and sources); they are the sum of the records you can list. Requires the token's\n * user to edit the offering's company.\n *\n */\nexport const getOfferingStats = <ThrowOnError extends boolean = false>(\n options: Options<GetOfferingStatsData, ThrowOnError>,\n): RequestResult<\n GetOfferingStatsResponses,\n GetOfferingStatsErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n GetOfferingStatsResponses,\n GetOfferingStatsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/offerings/{offering_id}/stats\",\n ...options,\n });\n\n/**\n * Bootstrap or page investment changes for a company\n *\n * The Investment Delta API: keep a copy of a company's investment records in sync by\n * polling. Call without `cursor` to **bootstrap** (list every current record for the\n * company); every response carries `meta.next_cursor`; call again with that cursor to\n * receive only the records whose published state changed since. Records are the same\n * shape in both modes.\n *\n * - Records are **published state**, not live rows: Wefunder publishes a record when the\n * investment's founder-visible state changes, and serves exactly what was published.\n * - `visible: false` records are **tombstones**: the investment is no longer visible to the\n * company (canceled, converted to another round, hidden, or deleted). Delete your copy.\n * - Apply records in `cursor` order. `observed_at` is when the payload was observed, not a\n * version; a record you read late carries the *current* published state.\n * - **410 Gone** means your cursor predates the 90-day retention window. Bootstrap again and\n * **replace** your dataset for the company from the result (records absent from the\n * bootstrap are deleted).\n * - Investor identity fields (`investor.name`, `investor.legal_name`, `investor.email`,\n * `investor.address`, `investor.bio`, `message`, `external_username`) are **omitted**\n * unless the token carries `read:investors:pii`.\n * - Money is integer minor units plus `amounts.currency` (`committed_cents`,\n * `investment_size_cents`, `in_escrow_cents`, `contracts[].override_amount_cents`).\n * `shares` and `average_share_price` are decimal strings, `null` on rounds without shares.\n * `amounts.raised_cents` is the row's contribution to the public raised figure (0 while\n * `needs_whitelisting`); sum it, not `committed_cents`, to match the deal page.\n *\n */\nexport const listCompanyInvestmentChanges = <\n ThrowOnError extends boolean = false,\n>(\n options: Options<ListCompanyInvestmentChangesData, ThrowOnError>,\n): RequestResult<\n ListCompanyInvestmentChangesResponses,\n ListCompanyInvestmentChangesErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n ListCompanyInvestmentChangesResponses,\n ListCompanyInvestmentChangesErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/companies/{company_id}/investments/changes\",\n ...options,\n });\n\n/**\n * Get portfolio summary\n *\n * Returns totals across the authenticated investor's portfolio: cost basis,\n * current value, realized and unrealized gains, and per-status position counts.\n * Accepts the same `status` and `company` filters as `GET /portfolio/positions`\n * to total a slice of the portfolio, such as only exited positions.\n *\n * Requires a user-authorized token. App-only (client credentials) tokens\n * receive 403.\n *\n * Portfolio values are recalculated periodically rather than on each request,\n * so recent investments and valuation changes can take a few minutes to appear.\n * `as_of` is the timestamp of the oldest calculation included in the response.\n *\n * Monetary values are **integer cents**; per-share prices and return multiples\n * are **decimal strings**.\n *\n */\nexport const getPortfolio = <ThrowOnError extends boolean = false>(\n options?: Options<GetPortfolioData, ThrowOnError>,\n): RequestResult<GetPortfolioResponses, GetPortfolioErrors, ThrowOnError> =>\n (options?.client ?? client).get<\n GetPortfolioResponses,\n GetPortfolioErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/portfolio\",\n ...options,\n });\n\n/**\n * List portfolio positions\n *\n * Returns the authenticated investor's positions, one per offering\n * (fundraise), newest first. Position totals cover everything the investor\n * holds in that offering; `securities` breaks the total down by security\n * offering and legal owner, so early bird tiers and personally-held vs\n * entity-held stakes each appear separately. Fund and SPV positions identify\n * the companies the vehicle invested in under `holdings`.\n *\n * To compute an average cost per share, divide `cost_basis_cents` by\n * `shares_held`.\n *\n * Requires a user-authorized token, like `GET /portfolio`.\n *\n */\nexport const listPortfolioPositions = <ThrowOnError extends boolean = false>(\n options?: Options<ListPortfolioPositionsData, ThrowOnError>,\n): RequestResult<\n ListPortfolioPositionsResponses,\n ListPortfolioPositionsErrors,\n ThrowOnError\n> =>\n (options?.client ?? client).get<\n ListPortfolioPositionsResponses,\n ListPortfolioPositionsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/portfolio/positions\",\n ...options,\n });\n\n/**\n * List founder campaigns\n *\n * Retrieves all fundraising campaigns for companies where the authenticated user is a founder.\n * This endpoint returns comprehensive campaign data including funding progress, investor counts,\n * and campaign status.\n *\n * Use this endpoint to:\n * - Build custom founder dashboards\n * - Monitor fundraising progress across multiple campaigns\n * - Generate reports on campaign performance\n * - Integrate campaign data into your own tools\n *\n * Only founders with the appropriate permissions can access this endpoint. The response includes\n * both active and closed campaigns, with detailed metrics for each.\n *\n */\nexport const listCampaigns = <ThrowOnError extends boolean = false>(\n options?: Options<ListCampaignsData, ThrowOnError>,\n): RequestResult<ListCampaignsResponses, ListCampaignsErrors, ThrowOnError> =>\n (options?.client ?? client).get<\n ListCampaignsResponses,\n ListCampaignsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/campaigns\",\n ...options,\n });\n\n/**\n * List syndicates\n *\n * Returns syndicates the authenticated user can manage, based on their roles.\n * Results can be filtered by status and sorted by name or creation date.\n *\n */\nexport const listSyndicates = <ThrowOnError extends boolean = false>(\n options?: Options<ListSyndicatesData, ThrowOnError>,\n): RequestResult<ListSyndicatesResponses, ListSyndicatesErrors, ThrowOnError> =>\n (options?.client ?? client).get<\n ListSyndicatesResponses,\n ListSyndicatesErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates\",\n ...options,\n });\n\n/**\n * Get syndicate details\n *\n * Returns full details for a specific syndicate including settings, team configuration, and summary metrics.\n */\nexport const getSyndicate = <ThrowOnError extends boolean = false>(\n options: Options<GetSyndicateData, ThrowOnError>,\n): RequestResult<GetSyndicateResponses, GetSyndicateErrors, ThrowOnError> =>\n (options.client ?? client).get<\n GetSyndicateResponses,\n GetSyndicateErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}\",\n ...options,\n });\n\n/**\n * Update syndicate settings\n *\n * Update syndicate configuration. Currently supports name, description, and tagline.\n * Requires `write:syndicates` scope and at least operator permission.\n *\n */\nexport const updateSyndicate = <ThrowOnError extends boolean = false>(\n options: Options<UpdateSyndicateData, ThrowOnError>,\n): RequestResult<\n UpdateSyndicateResponses,\n UpdateSyndicateErrors,\n ThrowOnError\n> =>\n (options.client ?? client).patch<\n UpdateSyndicateResponses,\n UpdateSyndicateErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * List members\n *\n * Returns the member directory for a syndicate with role, status, tags, sidebar notes,\n * and investment history summaries. Supports filtering, sorting, search, and pagination.\n *\n */\nexport const listSyndicateMembers = <ThrowOnError extends boolean = false>(\n options: Options<ListSyndicateMembersData, ThrowOnError>,\n): RequestResult<\n ListSyndicateMembersResponses,\n ListSyndicateMembersErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n ListSyndicateMembersResponses,\n ListSyndicateMembersErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members\",\n ...options,\n });\n\n/**\n * Invite member\n *\n * Send an invitation to join the syndicate by email.\n */\nexport const inviteSyndicateMember = <ThrowOnError extends boolean = false>(\n options: Options<InviteSyndicateMemberData, ThrowOnError>,\n): RequestResult<\n InviteSyndicateMemberResponses,\n InviteSyndicateMemberErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n InviteSyndicateMemberResponses,\n InviteSyndicateMemberErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members/invite\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * Remove member (requires intent)\n *\n * Removing a member is irreversible and requires human approval through the Intent system.\n * This endpoint always returns 422 with a `use_intents` error directing you to\n * `POST /intents` with action `syndicates.remove_member`.\n *\n */\nexport const removeSyndicateMember = <ThrowOnError extends boolean = false>(\n options: Options<RemoveSyndicateMemberData, ThrowOnError>,\n): RequestResult<unknown, RemoveSyndicateMemberErrors, ThrowOnError> =>\n (options.client ?? client).delete<\n unknown,\n RemoveSyndicateMemberErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members/{member_id}\",\n ...options,\n });\n\n/**\n * Update member\n *\n * Update title and carry override for a member. Requires operator permission.\n */\nexport const updateSyndicateMember = <ThrowOnError extends boolean = false>(\n options: Options<UpdateSyndicateMemberData, ThrowOnError>,\n): RequestResult<\n UpdateSyndicateMemberResponses,\n UpdateSyndicateMemberErrors,\n ThrowOnError\n> =>\n (options.client ?? client).patch<\n UpdateSyndicateMemberResponses,\n UpdateSyndicateMemberErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members/{member_id}\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * Approve applicant\n *\n * Approve a pending applicant. Only applicants can be approved via API; invitees must accept their invite link.\n */\nexport const approveSyndicateMember = <ThrowOnError extends boolean = false>(\n options: Options<ApproveSyndicateMemberData, ThrowOnError>,\n): RequestResult<\n ApproveSyndicateMemberResponses,\n ApproveSyndicateMemberErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n ApproveSyndicateMemberResponses,\n ApproveSyndicateMemberErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members/{member_id}/approve\",\n ...options,\n });\n\n/**\n * Exile member\n *\n * Exile (hide) a member from the syndicate. Sets their role to exiled.\n */\nexport const hideSyndicateMember = <ThrowOnError extends boolean = false>(\n options: Options<HideSyndicateMemberData, ThrowOnError>,\n): RequestResult<\n HideSyndicateMemberResponses,\n HideSyndicateMemberErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n HideSyndicateMemberResponses,\n HideSyndicateMemberErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members/{member_id}/hide\",\n ...options,\n });\n\n/**\n * Promote member to admin\n *\n * Promote a member to full_access (admin) role. Only the syndicate creator can promote members.\n */\nexport const promoteSyndicateMember = <ThrowOnError extends boolean = false>(\n options: Options<PromoteSyndicateMemberData, ThrowOnError>,\n): RequestResult<\n PromoteSyndicateMemberResponses,\n PromoteSyndicateMemberErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n PromoteSyndicateMemberResponses,\n PromoteSyndicateMemberErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members/{member_id}/promote\",\n ...options,\n });\n\n/**\n * Demote member to operator\n *\n * Demote a member from full_access (admin) to operator permission.\n */\nexport const demoteSyndicateMember = <ThrowOnError extends boolean = false>(\n options: Options<DemoteSyndicateMemberData, ThrowOnError>,\n): RequestResult<\n DemoteSyndicateMemberResponses,\n DemoteSyndicateMemberErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n DemoteSyndicateMemberResponses,\n DemoteSyndicateMemberErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members/{member_id}/demote\",\n ...options,\n });\n\n/**\n * Restore exiled or resigned member\n *\n * Restore a member who was previously exiled or resigned. Sets their role back to member.\n */\nexport const restoreSyndicateMember = <ThrowOnError extends boolean = false>(\n options: Options<RestoreSyndicateMemberData, ThrowOnError>,\n): RequestResult<\n RestoreSyndicateMemberResponses,\n RestoreSyndicateMemberErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n RestoreSyndicateMemberResponses,\n RestoreSyndicateMemberErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members/{member_id}/restore\",\n ...options,\n });\n\n/**\n * Resend invitation\n */\nexport const resendSyndicateInvite = <ThrowOnError extends boolean = false>(\n options: Options<ResendSyndicateInviteData, ThrowOnError>,\n): RequestResult<\n ResendSyndicateInviteResponses,\n ResendSyndicateInviteErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n ResendSyndicateInviteResponses,\n ResendSyndicateInviteErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members/{member_id}/resend_invite\",\n ...options,\n });\n\n/**\n * Reorder members\n *\n * Set the display order for the member directory.\n */\nexport const reorderSyndicateMembers = <ThrowOnError extends boolean = false>(\n options: Options<ReorderSyndicateMembersData, ThrowOnError>,\n): RequestResult<\n ReorderSyndicateMembersResponses,\n ReorderSyndicateMembersErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n ReorderSyndicateMembersResponses,\n ReorderSyndicateMembersErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members/reorder\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * Export members CSV\n *\n * Generate a CSV export of the member directory. Returns the CSV data directly\n * with Content-Type text/csv. Requires operator permission.\n *\n */\nexport const exportSyndicateMembersCsv = <ThrowOnError extends boolean = false>(\n options: Options<ExportSyndicateMembersCsvData, ThrowOnError>,\n): RequestResult<\n ExportSyndicateMembersCsvResponses,\n ExportSyndicateMembersCsvErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n ExportSyndicateMembersCsvResponses,\n ExportSyndicateMembersCsvErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members/export_csv\",\n ...options,\n });\n\n/**\n * List deals\n *\n * Returns the syndicate's **live** deals (open, oversubscribed, or closing) with status,\n * terms, and metrics. Closed and upcoming rounds are not listed; `statistics.total_deals`\n * counts all linked rounds.\n *\n */\nexport const listSyndicateDeals = <ThrowOnError extends boolean = false>(\n options: Options<ListSyndicateDealsData, ThrowOnError>,\n): RequestResult<\n ListSyndicateDealsResponses,\n ListSyndicateDealsErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n ListSyndicateDealsResponses,\n ListSyndicateDealsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/deals\",\n ...options,\n });\n\n/**\n * Get deal details\n *\n * Returns full details for a specific deal including investor breakdown.\n */\nexport const getSyndicateDeal = <ThrowOnError extends boolean = false>(\n options: Options<GetSyndicateDealData, ThrowOnError>,\n): RequestResult<\n GetSyndicateDealResponses,\n GetSyndicateDealErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n GetSyndicateDealResponses,\n GetSyndicateDealErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/deals/{fundraise_id}\",\n ...options,\n });\n\n/**\n * List deal investors\n *\n * Returns syndicate members who invested in this deal. Results are scoped to\n * syndicate member user IDs only and sorted by amount descending.\n *\n * The `user_email` field is **moderator-only** — it returns null for non-moderator\n * callers (i.e., users who are not a manager/operator of the syndicate).\n *\n * `amount` is whole dollars as a string (e.g. `\"5000\"` is $5,000).\n *\n * Offset-paginated: pass `offset` and `per_page`; `meta` carries `total_count`,\n * `offset`, `per_page`, and `has_more`. Without `per_page` the full list is returned.\n *\n */\nexport const listSyndicateDealInvestors = <\n ThrowOnError extends boolean = false,\n>(\n options: Options<ListSyndicateDealInvestorsData, ThrowOnError>,\n): RequestResult<\n ListSyndicateDealInvestorsResponses,\n ListSyndicateDealInvestorsErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n ListSyndicateDealInvestorsResponses,\n ListSyndicateDealInvestorsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/deals/{fundraise_id}/investors\",\n ...options,\n });\n\n/**\n * List member investments\n *\n * Returns this member's investments in syndicate deals. Scoped to the syndicate's\n * selected deals (one per company, matching directory semantics). **Moderator-only.**\n *\n * `amount` and `meta.total_amount` are whole dollars as strings.\n *\n */\nexport const listSyndicateMemberInvestments = <\n ThrowOnError extends boolean = false,\n>(\n options: Options<ListSyndicateMemberInvestmentsData, ThrowOnError>,\n): RequestResult<\n ListSyndicateMemberInvestmentsResponses,\n ListSyndicateMemberInvestmentsErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n ListSyndicateMemberInvestmentsResponses,\n ListSyndicateMemberInvestmentsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/members/{member_id}/investments\",\n ...options,\n });\n\n/**\n * Get syndicate statistics\n *\n * Returns aggregate metrics for a syndicate including member counts, deal counts,\n * total raised, and recent activity.\n *\n * `total_raised` and `total_investors` are computed from directory-selected deals\n * (one per company). `total_deals` and `live_deals` use all linked deals.\n *\n * `total_raised` is whole dollars as a string.\n *\n */\nexport const getSyndicateStatistics = <ThrowOnError extends boolean = false>(\n options: Options<GetSyndicateStatisticsData, ThrowOnError>,\n): RequestResult<\n GetSyndicateStatisticsResponses,\n GetSyndicateStatisticsErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n GetSyndicateStatisticsResponses,\n GetSyndicateStatisticsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/statistics\",\n ...options,\n });\n\n/**\n * Get syndicate portfolio summary\n *\n * Returns totals across the syndicate's portfolio: cost basis, current value,\n * gains, per-status deal counts, and the number of distinct investors.\n * Accepts the same `status` and `company` filters as the positions endpoint\n * to total a slice of the portfolio, such as only exited deals.\n *\n * The summary covers the syndicate's funded deals, summed across everyone\n * holding their securities (not just current members), as aggregate figures\n * only. Member-level data is available on the members endpoints.\n *\n * Portfolio values are recalculated periodically rather than on each request,\n * so recent investments and valuation changes can take a few minutes to appear.\n * `as_of` is the timestamp of the oldest calculation included in the response.\n *\n * Monetary values are **integer cents**; per-share prices and return multiples\n * are **decimal strings**.\n *\n */\nexport const getSyndicatePortfolio = <ThrowOnError extends boolean = false>(\n options: Options<GetSyndicatePortfolioData, ThrowOnError>,\n): RequestResult<\n GetSyndicatePortfolioResponses,\n GetSyndicatePortfolioErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n GetSyndicatePortfolioResponses,\n GetSyndicatePortfolioErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/portfolio\",\n ...options,\n });\n\n/**\n * List syndicate portfolio positions\n *\n * Returns the syndicate's portfolio one deal at a time, newest first. Each\n * position is one fundraise (\"offering\"), aggregated across everyone holding\n * its securities, with `investor_count` at both the position and security\n * level.\n *\n * `securities` breaks each position down by security offering (for example,\n * an early bird tier vs the regular terms) — most deals have a single entry.\n * Fund and SPV deals identify the companies the vehicle invested in under\n * `holdings`; some older vehicles have no recorded holdings and return an\n * empty array.\n *\n */\nexport const listSyndicatePortfolioPositions = <\n ThrowOnError extends boolean = false,\n>(\n options: Options<ListSyndicatePortfolioPositionsData, ThrowOnError>,\n): RequestResult<\n ListSyndicatePortfolioPositionsResponses,\n ListSyndicatePortfolioPositionsErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n ListSyndicatePortfolioPositionsResponses,\n ListSyndicatePortfolioPositionsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/portfolio/positions\",\n ...options,\n });\n\n/**\n * Close deal\n *\n * Closing a deal is irreversible and requires human approval through the Intent system.\n * This endpoint server-mints a pending `syndicates.close_deal` intent and returns the deal\n * under `data` plus the intent's `review_url` under `meta.close_deal_intent`. The deal is\n * not transitioned until a permitted human approves the intent in the Wefunder UI.\n * Idempotent: a repeated call returns the same pending intent rather than minting a duplicate.\n *\n */\nexport const closeSyndicateDeal = <ThrowOnError extends boolean = false>(\n options: Options<CloseSyndicateDealData, ThrowOnError>,\n): RequestResult<\n CloseSyndicateDealResponses,\n CloseSyndicateDealErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n CloseSyndicateDealResponses,\n CloseSyndicateDealErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/deals/{fundraise_id}/close\",\n ...options,\n });\n\n/**\n * Finalize deal\n *\n * Finalizing a deal is irreversible and requires human approval through the Intent system.\n * This endpoint server-mints a pending `syndicates.finalize_deal` intent and returns the\n * deal under `data` plus the intent's `review_url` under `meta.finalize_deal_intent`. The\n * finalize runs only when a permitted human approves the intent in the Wefunder UI.\n * Idempotent: a repeated call returns the same pending intent rather than minting a duplicate.\n *\n */\nexport const finalizeSyndicateDeal = <ThrowOnError extends boolean = false>(\n options: Options<FinalizeSyndicateDealData, ThrowOnError>,\n): RequestResult<\n FinalizeSyndicateDealResponses,\n FinalizeSyndicateDealErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n FinalizeSyndicateDealResponses,\n FinalizeSyndicateDealErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/syndicates/{syndicate_id}/deals/{fundraise_id}/finalize\",\n ...options,\n });\n\n/**\n * Preview an intent without proposing it\n *\n * Runs every check `POST /intents` runs — the action's feature flag, resource type and id,\n * token binding, who may propose, and the handler's own validation — and returns what the\n * reviewer would read, without minting anything. The draft step for agents: admitted by any\n * proposing scope **or** `read:explore`, and the action's own scope is not required, so a user\n * can shape the text before granting the write permission. Same request body as `POST /intents`\n * (without `idempotency_key`). Errors are the same as `POST /intents` would give.\n *\n */\nexport const previewIntent = <ThrowOnError extends boolean = false>(\n options: Options<PreviewIntentData, ThrowOnError>,\n): RequestResult<PreviewIntentResponses, PreviewIntentErrors, ThrowOnError> =>\n (options.client ?? client).post<\n PreviewIntentResponses,\n PreviewIntentErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/intents/preview\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * List intents\n *\n * List intents created by the current token, optionally filtered by status or resource.\n */\nexport const listIntents = <ThrowOnError extends boolean = false>(\n options?: Options<ListIntentsData, ThrowOnError>,\n): RequestResult<ListIntentsResponses, ListIntentsErrors, ThrowOnError> =>\n (options?.client ?? client).get<\n ListIntentsResponses,\n ListIntentsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/intents\",\n ...options,\n });\n\n/**\n * Propose an intent\n *\n * Propose a dangerous or irreversible action for human approval. Returns a `review_url`\n * where a human must review the impact and approve before the action executes.\n *\n * The entity that proposes an intent can never approve it. Approval always happens\n * on Wefunder's UI by a user with permission on the resource.\n *\n * Each action names the scope that may propose it and the resource type it targets\n * (`syndicates.*` → `write:syndicates` on a syndicate; `comments.create` → `write:comments`\n * on a `Company`). The token must hold that action's scope; holding another proposing scope\n * is not enough (403 `insufficient_scope`).\n *\n * `comments.create` posts a question on a company's Ask tab, or an answer to one, as the\n * requesting user once they approve on wefunder.com. `resource_id` is the company (`co_...`);\n * `params` is `{ target_type: \"company\" | \"comment\", target: \"co_...\" | \"cmt_...\", body,\n * disclosure_key? }` (`disclosure_key` ∈ investor, stockholder, promoter, financial_stakeholder).\n * Who may post is the site's own rule: anyone the page is available to may ask (unless the\n * company has closed questions); only the company's team may answer. Only the requester can\n * approve. 20 proposals per user per day (429).\n *\n * An `idempotency_key` names one operation. Reusing it for the same operation returns the\n * existing intent (200) while that intent is pending, approved, executing, or executed;\n * reusing it for a different action, resource, or params is a 409 `idempotency_conflict`.\n *\n * An action still rolling out per account returns 403 `feature_disabled` for a user who is\n * not yet enabled. `POST /intents/preview` runs the same checks without minting.\n *\n * See [Intents documentation](/concepts/intents) for the full pattern.\n *\n */\nexport const createIntent = <ThrowOnError extends boolean = false>(\n options: Options<CreateIntentData, ThrowOnError>,\n): RequestResult<CreateIntentResponses, CreateIntentErrors, ThrowOnError> =>\n (options.client ?? client).post<\n CreateIntentResponses,\n CreateIntentErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/intents\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * Get intent status\n *\n * Check the current status of an intent. Use this to poll for approval\n * after proposing an intent, or subscribe to `intent.*` webhook events instead.\n *\n */\nexport const getIntent = <ThrowOnError extends boolean = false>(\n options: Options<GetIntentData, ThrowOnError>,\n): RequestResult<GetIntentResponses, GetIntentErrors, ThrowOnError> =>\n (options.client ?? client).get<\n GetIntentResponses,\n GetIntentErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/intents/{intent_id}\",\n ...options,\n });\n\n/**\n * List activity events\n *\n * Returns actions taken by OAuth apps authorized by the current user.\n * This is the API backing the user-facing activity feed at Settings > Activity.\n *\n */\nexport const listActivity = <ThrowOnError extends boolean = false>(\n options?: Options<ListActivityData, ThrowOnError>,\n): RequestResult<ListActivityResponses, ListActivityErrors, ThrowOnError> =>\n (options?.client ?? client).get<\n ListActivityResponses,\n ListActivityErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/activity\",\n ...options,\n });\n\n/**\n * List connected apps\n *\n * Returns all OAuth apps the user has authorized, with summary stats.\n */\nexport const listConnectedApps = <ThrowOnError extends boolean = false>(\n options?: Options<ListConnectedAppsData, ThrowOnError>,\n): RequestResult<\n ListConnectedAppsResponses,\n ListConnectedAppsErrors,\n ThrowOnError\n> =>\n (options?.client ?? client).get<\n ListConnectedAppsResponses,\n ListConnectedAppsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/connected-apps\",\n ...options,\n });\n\n/**\n * Revoke connected app\n *\n * Revoke all tokens for this app. Any pending intents from this app are automatically expired.\n *\n */\nexport const revokeConnectedApp = <ThrowOnError extends boolean = false>(\n options: Options<RevokeConnectedAppData, ThrowOnError>,\n): RequestResult<\n RevokeConnectedAppResponses,\n RevokeConnectedAppErrors,\n ThrowOnError\n> =>\n (options.client ?? client).delete<\n RevokeConnectedAppResponses,\n RevokeConnectedAppErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/connected-apps/{app_id}\",\n ...options,\n });\n\n/**\n * Get aggregate attribution statistics\n *\n * Returns aggregate attribution statistics for a campaign. This is a **Tier 0** endpoint\n * available to all OAuth applications with the `read:attribution:aggregate` scope.\n *\n * Use this endpoint to:\n * - Track overall marketing campaign performance\n * - Measure conversion rates by UTM source/campaign\n * - Monitor investment quality metrics\n * - Build performance dashboards\n *\n * The response includes totals and breakdowns by UTM parameters. All counts exclude\n * disputed attributions.\n *\n * **Privacy**: This endpoint returns aggregate data only. No individual investor\n * information is exposed.\n *\n */\nexport const getAttributionStats = <ThrowOnError extends boolean = false>(\n options: Options<GetAttributionStatsData, ThrowOnError>,\n): RequestResult<\n GetAttributionStatsResponses,\n GetAttributionStatsErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n GetAttributionStatsResponses,\n GetAttributionStatsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/campaigns/{campaign_id}/attribution/stats\",\n ...options,\n });\n\n/**\n * List attributed investments\n *\n * Returns a list of attributed investments. The detail level depends on your access:\n *\n * **Tier 1 (Marketing Partners)** - Anonymized data:\n * - Investor identity represented by opaque tokens (not real IDs)\n * - Tokens are campaign-scoped (different token per campaign for same investor)\n * - Investment amounts shown as tiers (small/medium/large), not exact values\n * - No PII (email, name, address) is returned\n *\n * **Tier 2 (Founders/Employees)** - Full data with `detail_level=full`:\n * - Real investment IDs (linkable to Wefunder admin)\n * - Investor name, email, and username\n * - Exact dollar amounts\n *\n * **Access**: Requires Tier 1+ access approval from Wefunder admin.\n *\n */\nexport const listAttributedInvestments = <ThrowOnError extends boolean = false>(\n options: Options<ListAttributedInvestmentsData, ThrowOnError>,\n): RequestResult<\n ListAttributedInvestmentsResponses,\n ListAttributedInvestmentsErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n ListAttributedInvestmentsResponses,\n ListAttributedInvestmentsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/campaigns/{campaign_id}/attribution/investments\",\n ...options,\n });\n\n/**\n * List installations of your app\n *\n * Where the calling application is installed. Someone who manages the app's organization sees\n * every install; anyone else sees the installs they made or could revoke. Revoked installs stay\n * listed for 30 days.\n *\n */\nexport const listInstallations = <ThrowOnError extends boolean = false>(\n options?: Options<ListInstallationsData, ThrowOnError>,\n): RequestResult<\n ListInstallationsResponses,\n ListInstallationsErrors,\n ThrowOnError\n> =>\n (options?.client ?? client).get<\n ListInstallationsResponses,\n ListInstallationsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/installations\",\n ...options,\n });\n\n/**\n * Install your app on a company or syndicate\n *\n * Installs the calling application on a company or syndicate the token's user can edit (or, for a\n * syndicate, manages), and mints the **company-owned token** the install stands for. The token\n * appears in this response only. Requires a token authorized by a user.\n *\n * The install is granted at the caller's tier (founder, admin or editor for a company). An\n * editor-tier install carries read scopes only; write scopes in `scopes` are dropped. Installing\n * on a company outside your own organization requires the app to be approved.\n *\n */\nexport const createInstallation = <ThrowOnError extends boolean = false>(\n options: Options<CreateInstallationData, ThrowOnError>,\n): RequestResult<\n CreateInstallationResponses,\n CreateInstallationErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n CreateInstallationResponses,\n CreateInstallationErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/installations\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * List where you can install your app\n *\n * Companies the token's user can edit and syndicates they manage, with the tier an install would\n * be granted at and the current install if one exists. Requires a token authorized by a user.\n *\n */\nexport const listEligibleInstallTargets = <\n ThrowOnError extends boolean = false,\n>(\n options?: Options<ListEligibleInstallTargetsData, ThrowOnError>,\n): RequestResult<\n ListEligibleInstallTargetsResponses,\n ListEligibleInstallTargetsErrors,\n ThrowOnError\n> =>\n (options?.client ?? client).get<\n ListEligibleInstallTargetsResponses,\n ListEligibleInstallTargetsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/installations/eligible\",\n ...options,\n });\n\n/**\n * Revoke an installation\n *\n * Revokes the install and every token issued for it. Requires a token authorized by a user who\n * can edit the company (or manages the syndicate), or who administers the app's organization.\n *\n */\nexport const revokeInstallation = <ThrowOnError extends boolean = false>(\n options: Options<RevokeInstallationData, ThrowOnError>,\n): RequestResult<\n RevokeInstallationResponses,\n RevokeInstallationErrors,\n ThrowOnError\n> =>\n (options.client ?? client).delete<\n RevokeInstallationResponses,\n RevokeInstallationErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/installations/{external_id}\",\n ...options,\n });\n\n/**\n * Retrieve an installation\n */\nexport const getInstallation = <ThrowOnError extends boolean = false>(\n options: Options<GetInstallationData, ThrowOnError>,\n): RequestResult<\n GetInstallationResponses,\n GetInstallationErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n GetInstallationResponses,\n GetInstallationErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/installations/{external_id}\",\n ...options,\n });\n\n/**\n * Mint a token for an installation\n *\n * Mints another company-owned token for an active install — for example one a founder made through\n * the install link. Scopes default to the install's grant and can only narrow it. The token appears\n * in this response only. Requires a token authorized by a user who installed it, could revoke it,\n * or manages the app's organization.\n *\n */\nexport const createInstallationToken = <ThrowOnError extends boolean = false>(\n options: Options<CreateInstallationTokenData, ThrowOnError>,\n): RequestResult<\n CreateInstallationTokenResponses,\n CreateInstallationTokenErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n CreateInstallationTokenResponses,\n CreateInstallationTokenErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/installations/{external_id}/tokens\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * List webhook endpoints\n *\n * Your application's webhook endpoints. The signing secret is never included. Requires an\n * owner, admin, or developer role in the application's organization.\n *\n */\nexport const listWebhookEndpoints = <ThrowOnError extends boolean = false>(\n options?: Options<ListWebhookEndpointsData, ThrowOnError>,\n): RequestResult<\n ListWebhookEndpointsResponses,\n ListWebhookEndpointsErrors,\n ThrowOnError\n> =>\n (options?.client ?? client).get<\n ListWebhookEndpointsResponses,\n ListWebhookEndpointsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/webhook_endpoints\",\n ...options,\n });\n\n/**\n * Create a webhook endpoint\n *\n * Registers an endpoint for your application. The response is the only time the\n * signing `secret` is returned; store it to verify signatures. Requires an\n * owner, admin, or developer role in the application's organization.\n *\n * On the sandbox API this returns `403 manage_endpoints_on_live_api`: create test\n * endpoints through the live API with `mode: \"test\"`, and they are mirrored into sandbox.\n *\n */\nexport const createWebhookEndpoint = <ThrowOnError extends boolean = false>(\n options: Options<CreateWebhookEndpointData, ThrowOnError>,\n): RequestResult<\n CreateWebhookEndpointResponses,\n CreateWebhookEndpointErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n CreateWebhookEndpointResponses,\n CreateWebhookEndpointErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/webhook_endpoints\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * Remove a webhook endpoint\n *\n * Stops deliveries immediately. The endpoint is retained as removed and cannot be restored.\n * Returns `403 manage_endpoints_on_live_api` on the sandbox API; use the live API.\n *\n */\nexport const deleteWebhookEndpoint = <ThrowOnError extends boolean = false>(\n options: Options<DeleteWebhookEndpointData, ThrowOnError>,\n): RequestResult<\n DeleteWebhookEndpointResponses,\n DeleteWebhookEndpointErrors,\n ThrowOnError\n> =>\n (options.client ?? client).delete<\n DeleteWebhookEndpointResponses,\n DeleteWebhookEndpointErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/webhook_endpoints/{external_id}\",\n ...options,\n });\n\n/**\n * Get a webhook endpoint\n *\n * Requires an owner, admin, or developer role in the application's organization.\n */\nexport const getWebhookEndpoint = <ThrowOnError extends boolean = false>(\n options: Options<GetWebhookEndpointData, ThrowOnError>,\n): RequestResult<\n GetWebhookEndpointResponses,\n GetWebhookEndpointErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n GetWebhookEndpointResponses,\n GetWebhookEndpointErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/webhook_endpoints/{external_id}\",\n ...options,\n });\n\n/**\n * Update a webhook endpoint\n *\n * `events` replaces the subscription list wholesale (no merge); omit it to leave it\n * unchanged. An endpoint must subscribe to at least one event, so `[]` and `null` are\n * rejected; delete the endpoint to stop all deliveries. Requires an org management role.\n * Returns `403 manage_endpoints_on_live_api` on the sandbox API; use the live API.\n *\n */\nexport const updateWebhookEndpoint = <ThrowOnError extends boolean = false>(\n options: Options<UpdateWebhookEndpointData, ThrowOnError>,\n): RequestResult<\n UpdateWebhookEndpointResponses,\n UpdateWebhookEndpointErrors,\n ThrowOnError\n> =>\n (options.client ?? client).patch<\n UpdateWebhookEndpointResponses,\n UpdateWebhookEndpointErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/webhook_endpoints/{external_id}\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * Rotate the signing secret\n *\n * Returns a new signing secret (shown once). The previous secret keeps signing for a\n * 24h overlap window, so deliveries carry a `v1` for both; verify against either.\n * Returns `403 manage_endpoints_on_live_api` on the sandbox API; use the live API.\n *\n */\nexport const rotateWebhookEndpointSecret = <\n ThrowOnError extends boolean = false,\n>(\n options: Options<RotateWebhookEndpointSecretData, ThrowOnError>,\n): RequestResult<\n RotateWebhookEndpointSecretResponses,\n RotateWebhookEndpointSecretErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n RotateWebhookEndpointSecretResponses,\n RotateWebhookEndpointSecretErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/webhook_endpoints/{external_id}/rotate_secret\",\n ...options,\n });\n\n/**\n * Re-enable a disabled endpoint\n *\n * Recovery after auto-disable. Idempotent. Requires an org management role on the live API.\n * Also allowed on the sandbox API for an endpoint sandbox itself disabled (sandbox runs its own\n * health checks on its mirror of a test endpoint), authorized by the caller's realm.\n *\n */\nexport const reenableWebhookEndpoint = <ThrowOnError extends boolean = false>(\n options: Options<ReenableWebhookEndpointData, ThrowOnError>,\n): RequestResult<\n ReenableWebhookEndpointResponses,\n ReenableWebhookEndpointErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n ReenableWebhookEndpointResponses,\n ReenableWebhookEndpointErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/webhook_endpoints/{external_id}/reenable\",\n ...options,\n });\n\n/**\n * Send a test event\n *\n * Sends a real, signed example event (fake values) using the production envelope,\n * signature scheme, and transport, and reports the outcome inline. Does not affect\n * delivery health. Rate-limited to 10 per minute per endpoint. Investor email appears\n * in the example only if your application holds `read:investors:pii`, matching what\n * real deliveries can carry.\n *\n */\nexport const testWebhookEndpoint = <ThrowOnError extends boolean = false>(\n options: Options<TestWebhookEndpointData, ThrowOnError>,\n): RequestResult<\n TestWebhookEndpointResponses,\n TestWebhookEndpointErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n TestWebhookEndpointResponses,\n TestWebhookEndpointErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/webhook_endpoints/{external_id}/test\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * List attribution webhook subscriptions\n *\n * Returns all active webhook subscriptions for this campaign belonging to\n * your OAuth application.\n *\n * **Tier 1** endpoint requiring admin-approved access with the\n * `read:attribution:anonymized` scope.\n *\n */\nexport const listWebhookSubscriptions = <ThrowOnError extends boolean = false>(\n options: Options<ListWebhookSubscriptionsData, ThrowOnError>,\n): RequestResult<\n ListWebhookSubscriptionsResponses,\n ListWebhookSubscriptionsErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n ListWebhookSubscriptionsResponses,\n ListWebhookSubscriptionsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/campaigns/{campaign_id}/attribution/webhooks\",\n ...options,\n });\n\n/**\n * Create webhook subscription\n *\n * Creates a new webhook subscription for this campaign. When attributed\n * investments change state, we'll POST a JSON payload to your target URL.\n *\n * **Tier 1** endpoint requiring admin-approved access.\n *\n * ## Webhook Payload\n *\n * Payloads include anonymized data (tokens, amount tiers) matching the\n * `/attribution/investments` endpoint.\n *\n * ## Security\n *\n * - `target_url` must use HTTPS\n * - `target_url` cannot resolve to private/internal IPs (SSRF protection)\n * - Payloads are signed with HMAC-SHA256 using the returned `secret`\n *\n * ## Verification\n *\n * Verify webhook signatures using the `X-Wefunder-Signature` header:\n * ```\n * timestamp = headers['X-Wefunder-Timestamp']\n * signature = headers['X-Wefunder-Signature']\n * expected = \"sha256=\" + HMAC-SHA256(secret, timestamp + \".\" + raw_body)\n * ```\n *\n * Reject requests where:\n * - Signature doesn't match\n * - Timestamp is more than 5 minutes old (replay protection)\n *\n */\nexport const createWebhookSubscription = <ThrowOnError extends boolean = false>(\n options: Options<CreateWebhookSubscriptionData, ThrowOnError>,\n): RequestResult<\n CreateWebhookSubscriptionResponses,\n CreateWebhookSubscriptionErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n CreateWebhookSubscriptionResponses,\n CreateWebhookSubscriptionErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/campaigns/{campaign_id}/attribution/webhooks\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * Delete webhook subscription\n *\n * Deactivates a webhook subscription. The subscription will stop receiving\n * events but historical delivery data is retained for 7 days.\n *\n */\nexport const deleteWebhookSubscription = <ThrowOnError extends boolean = false>(\n options: Options<DeleteWebhookSubscriptionData, ThrowOnError>,\n): RequestResult<\n DeleteWebhookSubscriptionResponses,\n DeleteWebhookSubscriptionErrors,\n ThrowOnError\n> =>\n (options.client ?? client).delete<\n DeleteWebhookSubscriptionResponses,\n DeleteWebhookSubscriptionErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/campaigns/{campaign_id}/attribution/webhooks/{webhook_id}\",\n ...options,\n });\n\n/**\n * Get webhook subscription details\n *\n * Returns details for a specific webhook subscription including recent\n * delivery history.\n *\n */\nexport const getWebhookSubscription = <ThrowOnError extends boolean = false>(\n options: Options<GetWebhookSubscriptionData, ThrowOnError>,\n): RequestResult<\n GetWebhookSubscriptionResponses,\n GetWebhookSubscriptionErrors,\n ThrowOnError\n> =>\n (options.client ?? client).get<\n GetWebhookSubscriptionResponses,\n GetWebhookSubscriptionErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/campaigns/{campaign_id}/attribution/webhooks/{webhook_id}\",\n ...options,\n });\n\n/**\n * Send test webhook\n *\n * Sends a test webhook to verify your endpoint is working correctly.\n * The test payload includes a `\"event\": \"test\"` field to distinguish\n * it from real events.\n *\n */\nexport const testWebhookSubscription = <ThrowOnError extends boolean = false>(\n options: Options<TestWebhookSubscriptionData, ThrowOnError>,\n): RequestResult<\n TestWebhookSubscriptionResponses,\n TestWebhookSubscriptionErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n TestWebhookSubscriptionResponses,\n TestWebhookSubscriptionErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/campaigns/{campaign_id}/attribution/webhooks/{webhook_id}/test\",\n ...options,\n });\n\n/**\n * Regenerate webhook signing secret\n *\n * Generates a new HMAC signing secret for the webhook subscription.\n * The old secret is immediately invalidated.\n *\n * **Important**: Store the new secret securely - it cannot be retrieved later.\n *\n */\nexport const regenerateWebhookSecret = <ThrowOnError extends boolean = false>(\n options: Options<RegenerateWebhookSecretData, ThrowOnError>,\n): RequestResult<\n RegenerateWebhookSecretResponses,\n RegenerateWebhookSecretErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n RegenerateWebhookSecretResponses,\n RegenerateWebhookSecretErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/campaigns/{campaign_id}/attribution/webhooks/{webhook_id}/regenerate_secret\",\n ...options,\n });\n\n/**\n * Reactivate disabled webhook\n *\n * Reactivates a webhook subscription that was auto-disabled after\n * consecutive failures. Resets the failure counter to 0.\n *\n * Use this after fixing issues with your webhook endpoint.\n *\n */\nexport const reactivateWebhookSubscription = <\n ThrowOnError extends boolean = false,\n>(\n options: Options<ReactivateWebhookSubscriptionData, ThrowOnError>,\n): RequestResult<\n ReactivateWebhookSubscriptionResponses,\n ReactivateWebhookSubscriptionErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n ReactivateWebhookSubscriptionResponses,\n ReactivateWebhookSubscriptionErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/campaigns/{campaign_id}/attribution/webhooks/{webhook_id}/reactivate\",\n ...options,\n });\n\n/**\n * Get current user's attribution profile\n *\n * Returns the authenticated user's marketing partner profile and connected campaigns.\n * If the user is not registered as a marketing partner, returns partner info as null.\n *\n */\nexport const getAttributionMe = <ThrowOnError extends boolean = false>(\n options?: Options<GetAttributionMeData, ThrowOnError>,\n): RequestResult<\n GetAttributionMeResponses,\n GetAttributionMeErrors,\n ThrowOnError\n> =>\n (options?.client ?? client).get<\n GetAttributionMeResponses,\n GetAttributionMeErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/attribution/me\",\n ...options,\n });\n\n/**\n * List campaigns accessible to the current user\n *\n * Returns all campaigns the authenticated user can access for attribution data.\n * For founders, this includes their own campaigns.\n * For marketing partners, this includes campaigns they've been granted access to.\n *\n */\nexport const listAttributionCampaigns = <ThrowOnError extends boolean = false>(\n options?: Options<ListAttributionCampaignsData, ThrowOnError>,\n): RequestResult<\n ListAttributionCampaignsResponses,\n ListAttributionCampaignsErrors,\n ThrowOnError\n> =>\n (options?.client ?? client).get<\n ListAttributionCampaignsResponses,\n ListAttributionCampaignsErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/attribution/campaigns\",\n ...options,\n });\n\n/**\n * Register as a marketing partner\n *\n * Registers the authenticated user as a marketing partner.\n * After registration, the partner can create invites to request access to campaigns.\n *\n */\nexport const registerAsPartner = <ThrowOnError extends boolean = false>(\n options: Options<RegisterAsPartnerData, ThrowOnError>,\n): RequestResult<\n RegisterAsPartnerResponses,\n RegisterAsPartnerErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n RegisterAsPartnerResponses,\n RegisterAsPartnerErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/attribution/partners/register\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * List partner invites\n *\n * Returns all invites created by or sent to the authenticated user.\n * Includes both pending and accepted invites.\n *\n */\nexport const listPartnerInvites = <ThrowOnError extends boolean = false>(\n options?: Options<ListPartnerInvitesData, ThrowOnError>,\n): RequestResult<\n ListPartnerInvitesResponses,\n ListPartnerInvitesErrors,\n ThrowOnError\n> =>\n (options?.client ?? client).get<\n ListPartnerInvitesResponses,\n ListPartnerInvitesErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/attribution/invites\",\n ...options,\n });\n\n/**\n * Create a partner invite\n *\n * Creates an invite to establish a partner-company connection.\n *\n * **Directions**:\n * - `partner_to_founder`: Marketing partner invites a founder to grant access\n * - `founder_to_partner`: Founder invites a marketing partner to access their campaign\n *\n * For `partner_to_founder`: Creates a shareable invite link.\n * For `founder_to_partner`: Sends an email to the partner.\n *\n */\nexport const createPartnerInvite = <ThrowOnError extends boolean = false>(\n options: Options<CreatePartnerInviteData, ThrowOnError>,\n): RequestResult<\n CreatePartnerInviteResponses,\n CreatePartnerInviteErrors,\n ThrowOnError\n> =>\n (options.client ?? client).post<\n CreatePartnerInviteResponses,\n CreatePartnerInviteErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/attribution/invites\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n/**\n * Revoke a partner invite\n *\n * Revokes a pending invite. Only the creator can revoke an invite.\n * Accepted invites cannot be revoked (delete the connection instead).\n *\n */\nexport const revokePartnerInvite = <ThrowOnError extends boolean = false>(\n options: Options<RevokePartnerInviteData, ThrowOnError>,\n): RequestResult<\n RevokePartnerInviteResponses,\n RevokePartnerInviteErrors,\n ThrowOnError\n> =>\n (options.client ?? client).delete<\n RevokePartnerInviteResponses,\n RevokePartnerInviteErrors,\n ThrowOnError\n >({\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: \"/attribution/invites/{token}\",\n ...options,\n });\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport {\n type Client,\n type ClientOptions,\n type Config,\n createClient,\n createConfig,\n} from \"./client\";\nimport type { ClientOptions as ClientOptions2 } from \"./types.gen\";\n\n/**\n * The `createClientConfig()` function will be called on client initialization\n * and the returned object will become the client's initial configuration.\n *\n * You may want to initialize your client this way instead of calling\n * `setConfig()`. This is useful for example if you're using Next.js\n * to ensure your client always has the correct values.\n */\nexport type CreateClientConfig<T extends ClientOptions = ClientOptions2> = (\n override?: Config<ClientOptions & T>,\n) => Config<Required<ClientOptions> & T>;\n\nexport const client: Client = createClient(\n createConfig<ClientOptions2>({ baseUrl: \"https://api.wefunder.com\" }),\n);\n","// The Wefunder client — the stable, hand-written public surface over the generated\n// layer. Wires: single API base (the edge proxy routes live/sandbox by token prefix,\n// so we do NOT route by prefix — plan §4.2 #1), a pinned Wefunder-Version, the\n// retry/refresh fetch wrapper, token rotation, typed-error unwrapping, and lazy\n// auto-pagination. Resource namespaces cover the common GA paths; `raw` exposes\n// every generated operation, pre-bound, as an escape hatch.\n\nimport { createClient, type Client } from \"./generated/client/index.js\";\nimport { createFetch, type RetryOptions } from \"./http.js\";\nimport { TokenManager, type TokenStore } from \"./token-manager.js\";\nimport { WefunderError, requestIdFrom } from \"./errors.js\";\nimport { WefunderTokenPersistenceError } from \"./token-manager.js\";\nimport {\n clientCredentialsGrant,\n type TokenSet,\n type OAuthHostOptions,\n} from \"./oauth.js\";\nimport { paginate, collect, type Cursor, type Page } from \"./pagination.js\";\nimport * as ops from \"./generated/sdk.gen.js\";\nimport type {\n User,\n InvestmentDeltaRecord,\n Offering,\n Campaign,\n Syndicate,\n Intent,\n AttributionMe,\n PortfolioPosition,\n PortfolioSummaryEnvelope,\n ListOfferingsData,\n ListIntentsData,\n ListInvestmentsData,\n GetPortfolioData,\n ListPortfolioPositionsData,\n WebhookEndpoint,\n WebhookEndpointListEnvelope,\n WebhookEndpointTestResultEnvelope,\n CreateWebhookEndpointData,\n UpdateWebhookEndpointData,\n DeleteWebhookEndpointResponses,\n} from \"./generated/types.gen.js\";\nimport type { WebhookEventName } from \"./webhooks.js\";\n\n/** Body for `wf.webhookEndpoints.create()`. */\nexport type CreateWebhookEndpointInput = CreateWebhookEndpointData[\"body\"];\n/** Body for `wf.webhookEndpoints.update()` — `events` replaces the list wholesale. */\nexport type UpdateWebhookEndpointInput = NonNullable<\n UpdateWebhookEndpointData[\"body\"]\n>;\n/** The list envelope, with `meta.quota` (max endpoints per app). */\nexport type WebhookEndpointList = WebhookEndpointListEnvelope;\n/** Outcome of `wf.webhookEndpoints.test()`. */\nexport type WebhookTestOutcome = NonNullable<\n WebhookEndpointTestResultEnvelope[\"data\"]\n>;\n/** Outcome of `wf.webhookEndpoints.remove()`. */\nexport type WebhookEndpointRemoved = NonNullable<\n DeleteWebhookEndpointResponses[200][\"data\"]\n>;\n\n/** Documented `sort` values for the offerings list, from the generated op. */\nexport type OfferingSort = NonNullable<ListOfferingsData[\"query\"]>[\"sort\"];\n/**\n * An investment record as `GET /investments` and `GET /investments/{id}` return it\n * (the Investment Delta shape — a full record or, for company audiences, a tombstone\n * with `visible: false`).\n */\nexport type Investment = InvestmentDeltaRecord;\n/** Filters + sync controls for `GET /investments` (`cursor` is managed by auto-pagination). */\nexport type InvestmentsQuery = NonNullable<ListInvestmentsData[\"query\"]>;\nexport type InvestmentsFilters = Omit<InvestmentsQuery, \"cursor\">;\n/** Documented `status` filter values for the intents list, from the generated op. */\nexport type IntentStatus = NonNullable<ListIntentsData[\"query\"]>[\"status\"];\n/** Portfolio summary filters shared with the positions endpoint. */\nexport type PortfolioFilters = NonNullable<GetPortfolioData[\"query\"]>;\n/** Portfolio status values documented by the API. */\nexport type PortfolioStatus = NonNullable<PortfolioFilters[\"status\"]>;\n/** Filters and pagination controls for portfolio positions. */\nexport type PortfolioPositionsQuery = NonNullable<\n ListPortfolioPositionsData[\"query\"]\n>;\n/** Portfolio position filters, excluding the cursor managed by auto-pagination. */\nexport type PortfolioPositionsFilters = Omit<PortfolioPositionsQuery, \"cursor\">;\n/** The summary resource inside the API's data envelope. */\nexport type PortfolioSummary = NonNullable<PortfolioSummaryEnvelope[\"data\"]>;\n\n// Version-free base — the edge gateway serves the API at the host root; `/api/v2`\n// remains a working back-compat alias. The API version is pinned via the\n// `Wefunder-Version` header (DEFAULT_API_VERSION), not the path.\nexport const DEFAULT_API_BASE_URL = \"https://api.wefunder.com\";\nexport const DEFAULT_API_VERSION = \"2025-01-15\";\n\nexport type Mode = \"live\" | \"test\" | \"unknown\";\n\nexport function modeForToken(token: string): Mode {\n if (token.startsWith(\"at_live_\")) return \"live\";\n if (token.startsWith(\"at_test_\")) return \"test\";\n return \"unknown\";\n}\n\nexport interface WefunderOptions extends OAuthHostOptions {\n /** A bearer access token. Either this or `tokens` is required. */\n accessToken?: string;\n /** A full token set (access + rotating refresh). Enables auto-refresh. */\n tokens?: TokenSet;\n /** Needed (with the refresh token) to auto-refresh on expiry/401. */\n clientId?: string;\n clientSecret?: string;\n /**\n * Marks this as a client_credentials client so the SDK auto-re-mints on expiry/401\n * (cc tokens have no refresh token). `fromClientCredentials` sets this for you.\n */\n clientCredentials?: { scopes?: string[] };\n apiVersion?: string;\n /** Override the API base. The edge proxy routes mode by token prefix — leave default in prod. */\n baseUrl?: string;\n // OAuth hosts (oauthBaseUrl / authorizeBaseUrl / tokenBaseUrl) come from OAuthHostOptions.\n store?: TokenStore;\n onTokenRefresh?: (tokens: TokenSet) => void | Promise<void>;\n retry?: RetryOptions;\n // --- injectables (testing) ---\n fetch?: typeof fetch;\n now?: () => number;\n sleep?: (ms: number) => Promise<void>;\n random?: () => number;\n}\n\ntype Result<T> = Promise<{ data?: T; error?: unknown; response?: Response }>;\n\n/** Every generated operation, pre-bound to this client. */\ntype RawOps = {\n [K in keyof typeof ops]: (typeof ops)[K] extends (o: infer O) => infer R\n ? (options?: Omit<O & object, \"client\">) => R\n : never;\n};\n\nexport class Wefunder {\n readonly mode: Mode;\n readonly raw: RawOps;\n #client: Client;\n #tokens: TokenManager;\n\n constructor(opts: WefunderOptions) {\n const tokenSet: TokenSet | undefined =\n opts.tokens ??\n (opts.accessToken ? { accessToken: opts.accessToken } : undefined);\n if (!tokenSet) {\n throw new Error(\"Wefunder: provide `accessToken` or `tokens`.\");\n }\n this.mode = modeForToken(tokenSet.accessToken);\n\n // For client_credentials clients, build a re-mint closure from the stored grant\n // inputs so the TokenManager can recover expired tokens (which have no refresh token).\n const reMint =\n opts.clientCredentials && opts.clientId && opts.clientSecret\n ? () =>\n clientCredentialsGrant({\n clientId: opts.clientId!,\n clientSecret: opts.clientSecret!,\n scopes: opts.clientCredentials!.scopes,\n oauthBaseUrl: opts.oauthBaseUrl,\n tokenBaseUrl: opts.tokenBaseUrl,\n fetch: opts.fetch,\n now: opts.now,\n })\n : undefined;\n\n this.#tokens = new TokenManager({\n tokens: tokenSet,\n clientId: opts.clientId,\n clientSecret: opts.clientSecret,\n reMint,\n oauthBaseUrl: opts.oauthBaseUrl,\n tokenBaseUrl: opts.tokenBaseUrl,\n onTokenRefresh: opts.onTokenRefresh,\n store: opts.store,\n fetch: opts.fetch,\n now: opts.now,\n });\n\n const wrappedFetch = createFetch({\n tokenManager: this.#tokens,\n fetch: opts.fetch,\n now: opts.now,\n sleep: opts.sleep,\n random: opts.random,\n retry: opts.retry,\n });\n\n this.#client = createClient({\n baseUrl: opts.baseUrl ?? DEFAULT_API_BASE_URL,\n headers: { \"Wefunder-Version\": opts.apiVersion ?? DEFAULT_API_VERSION },\n auth: () => this.#tokens.getAccessToken(),\n fetch: wrappedFetch,\n });\n\n this.raw = this.#buildRaw();\n }\n\n /** Server-to-server: exchange client credentials for a token, then build a client. */\n static async fromClientCredentials(\n opts: OAuthHostOptions & {\n clientId: string;\n clientSecret: string;\n scopes?: string[];\n apiVersion?: string;\n baseUrl?: string;\n fetch?: typeof fetch;\n now?: () => number;\n },\n ): Promise<Wefunder> {\n const tokens = await clientCredentialsGrant({\n clientId: opts.clientId,\n clientSecret: opts.clientSecret,\n scopes: opts.scopes,\n oauthBaseUrl: opts.oauthBaseUrl,\n tokenBaseUrl: opts.tokenBaseUrl,\n fetch: opts.fetch,\n now: opts.now,\n });\n return new Wefunder({\n tokens,\n clientId: opts.clientId,\n clientSecret: opts.clientSecret,\n clientCredentials: { scopes: opts.scopes }, // enables auto-re-mint on expiry/401\n oauthBaseUrl: opts.oauthBaseUrl,\n tokenBaseUrl: opts.tokenBaseUrl,\n apiVersion: opts.apiVersion,\n baseUrl: opts.baseUrl,\n fetch: opts.fetch,\n now: opts.now,\n });\n }\n\n /** The live token set (e.g. to persist after construction). */\n /** A rotated set awaiting a successful save (see `WefunderTokenPersistenceError`). */\n get pendingTokens(): TokenSet | undefined {\n return this.#tokens.pendingTokens;\n }\n\n /** Acknowledge an out-of-band save of `tokens`; false if that set is no longer pending. */\n markPersisted(tokens: TokenSet): Promise<boolean> {\n return this.#tokens.markPersisted(tokens);\n }\n\n get tokens(): TokenSet {\n return this.#tokens.current;\n }\n\n // ---- unwrap: turn the {data,error,response} result into data-or-throw ----\n async #unwrap<T>(p: Result<T>): Promise<T> {\n const { data, error, response } = await p;\n // Exceptions thrown by our own hooks (token recovery, persistence) are caught by the\n // generated client into `error`; surface them as-is rather than rebuilding a generic error.\n if (\n error instanceof WefunderTokenPersistenceError ||\n error instanceof WefunderError\n )\n throw error;\n if (response && response.ok && error === undefined) return data as T;\n const status = response?.status ?? 0;\n // The runtime error envelope nests request_id + remediation UNDER `error`\n // (api/v2/base_controller.rb#render_error), even though the spec's Error\n // schema models neither. Read them from there; fall back to top-level.\n const env = (error ?? {}) as {\n error?: {\n type?: string;\n message?: string;\n details?: unknown;\n request_id?: string;\n remediation?: string;\n };\n request_id?: string;\n };\n throw new WefunderError({\n status,\n type: env.error?.type ?? \"api_error\",\n message: env.error?.message ?? response?.statusText ?? \"Request failed\",\n // X-Wf-Request-Id header is primary (present even on non-JSON edge errors).\n requestId: requestIdFrom(\n response,\n env.error?.request_id ?? env.request_id,\n ),\n details: env.error?.details,\n remediation: env.error?.remediation,\n });\n }\n\n // Single-resource ops return a `{ data: Entity }` envelope; strip it for ergonomics.\n async #unwrapData<T>(p: Result<unknown>): Promise<T> {\n const env = await this.#unwrap<{ data?: T }>(p as Result<{ data?: T }>);\n return env.data as T;\n }\n\n #buildRaw(): RawOps {\n const raw = {} as Record<string, unknown>;\n for (const [name, fn] of Object.entries(ops)) {\n raw[name] = (options?: Record<string, unknown>) =>\n (fn as (o: unknown) => unknown)({ ...options, client: this.#client });\n }\n return raw as RawOps;\n }\n\n /**\n * Unwrap any generated op result (incl. `wf.raw.*`) the way the ergonomic\n * namespaces do: returns the response body on success, throws a typed\n * `WefunderError` (with `request_id`) on failure. Lets `raw` callers keep the\n * SDK's error handling. (Stress-test finding C.)\n */\n unwrap<T>(p: Result<T>): Promise<T> {\n return this.#unwrap(p);\n }\n\n // Generic page helper: forwards the endpoint's full query (cursor + documented\n // params like `sort`), not just the cursor. (Stress-test finding B.)\n #page<T, Q extends { cursor?: Cursor } = { cursor?: Cursor }>(\n fn: (o: { client: Client; query?: Q }) => Result<Page<T>>,\n ) {\n return (query?: Q): Promise<Page<T>> =>\n this.#unwrap(fn({ client: this.#client, query }) as Result<Page<T>>);\n }\n\n // ---- resource namespaces (common GA paths) ----\n\n users = {\n me: () =>\n this.#unwrapData<User>(ops.getCurrentUser({ client: this.#client })),\n };\n\n offerings = {\n list: this.#page<Offering, { cursor?: Cursor; sort?: OfferingSort }>(\n ops.listOfferings as never,\n ),\n all: (query?: { sort?: OfferingSort }): AsyncGenerator<Offering> =>\n paginate((cursor) => this.offerings.list({ ...query, cursor })),\n collect: (query?: { sort?: OfferingSort }): Promise<Offering[]> =>\n collect((cursor) => this.offerings.list({ ...query, cursor })),\n get: (externalId: string) =>\n this.#unwrapData<Offering>(\n ops.getOffering({\n client: this.#client,\n path: { external_id: externalId },\n }),\n ),\n };\n\n /**\n * Investments (`read:investments`). `list` is a bootstrap listing; pass `updated_since`\n * or a saved `cursor` for sync mode (`meta.mode === \"delta\"`). Persist `meta.next_cursor`\n * from your last page — it is always present — and resume from it next time.\n */\n investments = {\n list: this.#page<Investment, InvestmentsQuery>(\n ops.listInvestments as never,\n ),\n all: (query?: InvestmentsFilters): AsyncGenerator<Investment> =>\n paginate((cursor) =>\n this.investments.list({\n ...query,\n cursor: cursor as string | undefined,\n }),\n ),\n collect: (query?: InvestmentsFilters): Promise<Investment[]> =>\n collect((cursor) =>\n this.investments.list({\n ...query,\n cursor: cursor as string | undefined,\n }),\n ),\n /** The current record (not the published projection) for one investment (`inv_…`). */\n get: (id: string) =>\n this.#unwrapData<Investment>(\n ops.getInvestment({ client: this.#client, path: { id } }),\n ),\n };\n\n portfolio = {\n get: (query?: PortfolioFilters) =>\n this.#unwrapData<PortfolioSummary>(\n ops.getPortfolio({ client: this.#client, query }),\n ),\n positions: {\n list: this.#page<PortfolioPosition, PortfolioPositionsQuery>(\n ops.listPortfolioPositions as never,\n ),\n all: (\n query?: PortfolioPositionsFilters,\n ): AsyncGenerator<PortfolioPosition> =>\n paginate((cursor) =>\n this.portfolio.positions.list({ ...query, cursor: cursor as number }),\n ),\n collect: (\n query?: PortfolioPositionsFilters,\n ): Promise<PortfolioPosition[]> =>\n collect((cursor) =>\n this.portfolio.positions.list({ ...query, cursor: cursor as number }),\n ),\n },\n };\n\n campaigns = {\n list: this.#page<Campaign>(ops.listCampaigns as never),\n all: (): AsyncGenerator<Campaign> =>\n paginate((cursor) => this.campaigns.list({ cursor })),\n collect: (): Promise<Campaign[]> =>\n collect((cursor) => this.campaigns.list({ cursor })),\n };\n\n syndicates = {\n list: this.#page<Syndicate, { cursor?: Cursor; limit?: number }>(\n ops.listSyndicates as never,\n ),\n all: (query?: { limit?: number }): AsyncGenerator<Syndicate> =>\n paginate((cursor) => this.syndicates.list({ ...query, cursor })),\n get: (id: number | string) =>\n this.#unwrapData<Syndicate>(\n ops.getSyndicate({ client: this.#client, path: { id } as never }),\n ),\n };\n\n intents = {\n list: this.#page<\n Intent,\n {\n cursor?: Cursor;\n status?: IntentStatus;\n resource_type?: string;\n resource_id?: number;\n limit?: number;\n }\n >(ops.listIntents as never),\n all: (query?: {\n status?: IntentStatus;\n resource_type?: string;\n resource_id?: number;\n limit?: number;\n }): AsyncGenerator<Intent> =>\n paginate((cursor) => this.intents.list({ ...query, cursor })),\n get: (id: number | string) =>\n this.#unwrapData<Intent>(\n ops.getIntent({ client: this.#client, path: { id } as never }),\n ),\n };\n\n attribution = {\n me: () =>\n this.#unwrapData<AttributionMe>(\n ops.getAttributionMe({ client: this.#client }),\n ),\n };\n\n /**\n * Webhook endpoints (`/webhook_endpoints`, scopes `read:webhooks` / `write:webhooks`).\n * Endpoints belong to your application and are managed through the LIVE API —\n * create sandbox receivers there with `mode: \"test\"`; they're mirrored into\n * sandbox. The signing `secret` is returned ONLY by `create` and `rotateSecret`.\n * Verify deliveries with `constructEvent` (see the webhooks module).\n */\n webhookEndpoints = {\n /** All of your app's endpoints (secret omitted). `meta.quota` is the per-app limit. */\n list: (): Promise<WebhookEndpointList> =>\n this.#unwrap<WebhookEndpointList>(\n ops.listWebhookEndpoints({ client: this.#client }),\n ),\n get: (id: string) =>\n this.#unwrapData<WebhookEndpoint>(\n ops.getWebhookEndpoint({\n client: this.#client,\n path: { external_id: id },\n }),\n ),\n /** Store `attributes.secret` from the result — it is never shown again. */\n create: (input: CreateWebhookEndpointInput) =>\n this.#unwrapData<WebhookEndpoint>(\n ops.createWebhookEndpoint({ client: this.#client, body: input }),\n ),\n /** `events` replaces the subscription list wholesale (no merge); omit to leave unchanged. */\n update: (id: string, input: UpdateWebhookEndpointInput) =>\n this.#unwrapData<WebhookEndpoint>(\n ops.updateWebhookEndpoint({\n client: this.#client,\n path: { external_id: id },\n body: input,\n }),\n ),\n /** Stops deliveries immediately. Removal is permanent — create a new endpoint to resume. */\n remove: (id: string) =>\n this.#unwrapData<WebhookEndpointRemoved>(\n ops.deleteWebhookEndpoint({\n client: this.#client,\n path: { external_id: id },\n }),\n ),\n /**\n * New secret (shown once). The old one keeps signing for a 24h overlap — deliveries\n * carry a `v1` for both, and `constructEvent` accepts either.\n */\n rotateSecret: (id: string) =>\n this.#unwrapData<WebhookEndpoint>(\n ops.rotateWebhookEndpointSecret({\n client: this.#client,\n path: { external_id: id },\n }),\n ),\n /** Recover an auto-disabled endpoint after fixing your server. Idempotent. */\n reenable: (id: string) =>\n this.#unwrapData<WebhookEndpoint>(\n ops.reenableWebhookEndpoint({\n client: this.#client,\n path: { external_id: id },\n }),\n ),\n /**\n * POST a real, signed example event at the endpoint (production envelope + signature)\n * and report the outcome inline. Defaults to the endpoint's first subscribed event.\n * Doesn't affect delivery health. Rate-limited to 10/min per endpoint.\n */\n test: (id: string, event?: WebhookEventName) =>\n this.#unwrapData<WebhookTestOutcome>(\n ops.testWebhookEndpoint({\n client: this.#client,\n path: { external_id: id },\n body: event ? { event } : undefined,\n }),\n ),\n };\n}\n","// Webhook verification + parsing for Wefunder platform events.\n//\n// The shipped scheme (docs.wefunder.com → Partner API → Webhooks → Verification;\n// app/models/webhook_endpoint.rb#signature_header) is a single Stripe-style header:\n//\n// Wefunder-Signature: t=<unix seconds>,v1=<hex>[,v1=<hex>]\n// v1 = HMAC-SHA256(secret, \"<t>.<raw_body>\")\n//\n// During a secret rotation the header carries one `v1` per active secret (24h\n// overlap); a delivery is valid if ANY `v1` matches. Consumers enforce a replay\n// tolerance on `t` (documented: 5 minutes). Every delivery body is the envelope\n// `{ id: \"evt_…\", event, created_at, mode, data }` — `id` is the dedup key.\n//\n// The retired attribution surface (`/campaigns/:id/attribution/webhooks`) signed\n// differently (`X-Wefunder-Signature: sha256=<hex>` + `X-Wefunder-Timestamp`).\n// `constructEvent` still accepts that shape so an attribution subscriber isn't\n// stranded, but everything new should target the platform-events scheme.\n\nimport { createHmac, timingSafeEqual } from \"node:crypto\";\nimport type { CreateWebhookEndpointData } from \"./generated/types.gen.js\";\n\n// ---------------------------------------------------------------------------\n// Event names + payload types\n// ---------------------------------------------------------------------------\n\n/**\n * Every event name in the catalog, derived from the spec's `events` enum on\n * `POST /webhook_endpoints` so it can't drift from the API.\n */\nexport type WebhookEventName = CreateWebhookEndpointData[\"body\"][\"events\"][number];\n\n/** Delivery mode — `test` for sandbox facts, `live` otherwise. */\nexport type WebhookMode = \"live\" | \"test\";\n\n/** A person reference on a payload: partner-visible id + name, never email. */\nexport interface WebhookPersonRef {\n id: string | null;\n name: string | null;\n}\n\n/** The investor on an `investment.*` event. `email` needs `read:investors:pii`. */\nexport interface WebhookInvestor {\n id: string | null;\n name?: string | null;\n email?: string | null;\n}\n\n/**\n * The investor across all of the company's offerings in the same raise, at the\n * moment of the event. Company-installed apps only.\n */\nexport interface WebhookInvestorTotals {\n active_investment_count: number;\n total_committed: number | string | null;\n latest_applied_at: string | null;\n investor_status: \"active\" | \"none_active\";\n}\n\n/** `data` for the `investment.*` lifecycle events (not `investment.changed`). */\nexport interface InvestmentEventData {\n /** The investment (`inv_…`). */\n id: string;\n status: \"reserved\" | \"active\" | \"executed\" | \"canceled\" | \"converted\";\n /** The offering (`ofr_…`). */\n offering: string | null;\n amounts: { committed: number | string | null };\n investor: WebhookInvestor;\n /** Company-installed apps only. Absent for user-connected apps. */\n investor_totals?: WebhookInvestorTotals;\n /** ISO 8601 with microseconds. Order events by this, not by arrival. Absent on `investment.executed`. */\n occurred_at?: string;\n /** `investment.canceled` only. */\n canceled_at?: string | null;\n /** `investment.converted` only — the successor (`inv_…`), or null if unresolved at conversion. */\n converted_to?: string | null;\n /** `investment.amount_changed` only. */\n previous_amounts?: { committed: number | string | null };\n}\n\n/** `data` for `investment.changed` — a thin sync nudge; fetch the record, don't trust the payload. */\nexport interface InvestmentChangedEventData {\n /** The investment (`inv_…`). */\n id: string;\n /** `false` means the investment is no longer visible to the company (a tombstone). */\n visible: boolean;\n reason: string;\n /** The company (`co_…`). */\n company: string | null;\n observed_at: string;\n}\n\n/** `data` for the `offering.*` events. */\nexport interface OfferingEventData {\n /** The offering (`ofr_…`). */\n offering: string | null;\n status: \"open\" | \"closing\" | \"closed\" | \"canceled\";\n company: { name: string | null; url: string | null };\n /** `offering.closing` only, when ops has an ETA for disbursement. */\n expected_disbursement_at?: string;\n}\n\n/** `data` for the `investment_session.*` events. */\nexport interface InvestmentSessionEventData {\n /** The session id. */\n id: string;\n status: string;\n /** The offering (`ofr_…`). */\n offering: string | null;\n email: string | null;\n allocation_cents: number | null;\n expires_at: string | null;\n /** The resulting investment (`inv_…`), once one exists. */\n investment?: string;\n}\n\n/** `data` for `syndicate_member.invited` / `syndicate_member.reinvited`. */\nexport interface SyndicateInvitationEventData {\n /** The syndicate (`syn_…`). */\n syndicate: string | null;\n email: string | null;\n name: string | null;\n /** The invitee's `usr_…` id when the address already belongs to an account, else null. */\n user: string | null;\n invited_by: WebhookPersonRef | null;\n occurred_at: string;\n}\n\n/** `data` for `syndicate_member.applied` / `.approved` / `.joined`. */\nexport interface SyndicateMemberEventData {\n /** The membership (`mem_…`). */\n id: string | null;\n /** The syndicate (`syn_…`). */\n syndicate: string | null;\n status: \"pending\" | \"approved\" | \"member\";\n user: { id: string | null; name: string | null; email: string | null };\n /** Null on an automatic or invited join. */\n approved_by: WebhookPersonRef | null;\n occurred_at: string;\n}\n\n/** Maps each event name to the documented shape of its `data`. */\nexport interface WebhookEventDataMap {\n \"investment.created\": InvestmentEventData;\n \"investment.reinstated\": InvestmentEventData;\n \"investment.canceled\": InvestmentEventData;\n \"investment.converted\": InvestmentEventData;\n \"investment.amount_changed\": InvestmentEventData;\n \"investment.executed\": InvestmentEventData;\n \"investment.changed\": InvestmentChangedEventData;\n \"offering.opened\": OfferingEventData;\n \"offering.closing\": OfferingEventData;\n \"offering.closed\": OfferingEventData;\n \"offering.canceled\": OfferingEventData;\n \"investment_session.created\": InvestmentSessionEventData;\n \"investment_session.started\": InvestmentSessionEventData;\n \"investment_session.completed\": InvestmentSessionEventData;\n \"investment_session.expired\": InvestmentSessionEventData;\n \"investment_session.canceled\": InvestmentSessionEventData;\n \"syndicate_member.invited\": SyndicateInvitationEventData;\n \"syndicate_member.reinvited\": SyndicateInvitationEventData;\n \"syndicate_member.applied\": SyndicateMemberEventData;\n \"syndicate_member.approved\": SyndicateMemberEventData;\n \"syndicate_member.joined\": SyndicateMemberEventData;\n}\n\n// Compile-time check: every catalog name has a payload type. If a spec sync adds\n// an event, `npm run typecheck` fails here until the map is extended.\ntype EveryEventIsTyped = WebhookEventName extends keyof WebhookEventDataMap ? true : never;\nconst everyEventIsTyped: EveryEventIsTyped = true;\nvoid everyEventIsTyped;\n\n/**\n * A verified, parsed delivery. Narrow on `event` to get a typed `data`:\n *\n * if (evt.event === \"investment.executed\") evt.data.amounts.committed\n */\nexport type WebhookEvent<E extends WebhookEventName = WebhookEventName> = {\n [K in E]: {\n /** Event id (`evt_…`) — the dedup key. Deliveries may repeat; ignore ids you've seen. */\n id: string;\n event: K;\n created_at: string;\n mode: WebhookMode;\n data: WebhookEventDataMap[K];\n /** The signed timestamp (`t`, unix seconds). */\n timestamp: number;\n };\n}[E];\n\n/**\n * A delivery whose `event` isn't in this SDK's catalog (newer than your installed\n * version). Still signature-verified; `data` is untyped.\n */\nexport interface UnknownWebhookEvent {\n id: string;\n event: string;\n created_at: string;\n mode: WebhookMode;\n data: unknown;\n timestamp: number;\n}\n\n// ---------------------------------------------------------------------------\n// Headers + errors\n// ---------------------------------------------------------------------------\n\n/** The platform-events signature header (case-insensitive). */\nexport const SIGNATURE_HEADER = \"wefunder-signature\";\n/** Documented consumer replay tolerance. */\nexport const DEFAULT_TOLERANCE_SECONDS = 300;\n\n/** @deprecated Attribution-era header; only relevant to legacy attribution subscriptions. */\nexport const LEGACY_SIGNATURE_HEADER = \"x-wefunder-signature\";\n/** @deprecated Attribution-era header; only relevant to legacy attribution subscriptions. */\nexport const LEGACY_TIMESTAMP_HEADER = \"x-wefunder-timestamp\";\n/** @deprecated Attribution-era header; only relevant to legacy attribution subscriptions. */\nexport const LEGACY_EVENT_HEADER = \"x-wefunder-event\";\n/** @deprecated Attribution-era header; only relevant to legacy attribution subscriptions. */\nexport const LEGACY_DELIVERY_ID_HEADER = \"x-wefunder-delivery-id\";\n\nexport type WebhookSignatureFailure =\n | \"missing_header\"\n | \"malformed_header\"\n | \"timestamp_out_of_tolerance\"\n | \"signature_mismatch\"\n | \"invalid_payload\";\n\n/** Thrown by `constructEvent` / `constructEventFromRequest`. Respond 400 and don't process. */\nexport class WebhookSignatureError extends Error {\n readonly reason: WebhookSignatureFailure;\n constructor(reason: WebhookSignatureFailure, message: string) {\n super(message);\n this.name = \"WebhookSignatureError\";\n this.reason = reason;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Signing primitives\n// ---------------------------------------------------------------------------\n\nexport type RawBody = string | Uint8Array;\n\nfunction bodyBuffer(payload: RawBody): Buffer {\n return typeof payload === \"string\" ? Buffer.from(payload, \"utf8\") : Buffer.from(payload);\n}\n\n/** `HMAC-SHA256(secret, \"<timestamp>.<rawBody>\")` as lowercase hex. */\nexport function computeWebhookSignature(secret: string, timestamp: number | string, payload: RawBody): string {\n return createHmac(\"sha256\", secret).update(`${timestamp}.`).update(bodyBuffer(payload)).digest(\"hex\");\n}\n\nfunction constantTimeEqual(a: string, b: string): boolean {\n const ab = Buffer.from(a);\n const bb = Buffer.from(b);\n if (ab.length !== bb.length) return false;\n return timingSafeEqual(ab, bb);\n}\n\n/** The parts of a `Wefunder-Signature` header. */\nexport interface ParsedSignatureHeader {\n timestamp: number;\n /** Every `v1` value (more than one during a secret rotation). */\n signatures: string[];\n}\n\n/** Parse `t=<unix>,v1=<hex>[,v1=<hex>]`. Returns null when the shape is wrong. */\nexport function parseSignatureHeader(header: string): ParsedSignatureHeader | null {\n let timestamp: number | undefined;\n const signatures: string[] = [];\n for (const part of header.split(\",\")) {\n const eq = part.indexOf(\"=\");\n if (eq < 0) continue;\n const key = part.slice(0, eq).trim();\n const value = part.slice(eq + 1).trim();\n if (key === \"t\") {\n if (!/^\\d+$/.test(value)) return null;\n timestamp = Number(value);\n } else if (key === \"v1\" && value) {\n signatures.push(value);\n }\n // Unknown keys (a future `v2`) are ignored on purpose — forward compatible.\n }\n if (timestamp === undefined || signatures.length === 0) return null;\n return { timestamp, signatures };\n}\n\nexport interface SignWebhookOptions {\n /** The exact bytes that will be sent as the body. */\n payload: RawBody;\n secret: string;\n /** Unix seconds. Defaults to now. */\n timestamp?: number;\n /**\n * Extra secrets to also sign with (adds one `v1` per secret) — simulates a\n * rotation window in tests.\n */\n additionalSecrets?: string[];\n}\n\n/**\n * Build a `Wefunder-Signature` header value for `payload`. For your own tests\n * (sign a fixture, POST it at your handler) — the API signs real deliveries.\n */\nexport function signWebhook(opts: SignWebhookOptions): string {\n const t = opts.timestamp ?? Math.floor(Date.now() / 1000);\n const secrets = [opts.secret, ...(opts.additionalSecrets ?? [])];\n const entries = secrets.map((s) => `v1=${computeWebhookSignature(s, t, opts.payload)}`);\n return [`t=${t}`, ...entries].join(\",\");\n}\n\n// ---------------------------------------------------------------------------\n// Verification\n// ---------------------------------------------------------------------------\n\nexport interface VerifyWebhookOptions {\n /** The exact raw request body (NOT a re-serialized object). */\n payload: RawBody;\n /** Value of the `Wefunder-Signature` header (`t=…,v1=…`). */\n header: string;\n secret: string;\n /** Reject if |now - t| exceeds this. Default 300s. Set 0 to disable. */\n toleranceSeconds?: number;\n /** Injectable clock (ms since epoch), for tests. */\n now?: () => number;\n}\n\n/**\n * Returns the reason a delivery is NOT valid, or null when it is. Constant-time\n * compare against every `v1`; enforces the timestamp tolerance.\n */\nexport function checkWebhookSignature(opts: VerifyWebhookOptions): WebhookSignatureFailure | null {\n const parsed = parseSignatureHeader(opts.header);\n if (!parsed) return \"malformed_header\";\n const tolerance = opts.toleranceSeconds ?? DEFAULT_TOLERANCE_SECONDS;\n if (tolerance > 0) {\n const nowSec = (opts.now ?? Date.now)() / 1000;\n if (Math.abs(nowSec - parsed.timestamp) > tolerance) return \"timestamp_out_of_tolerance\";\n }\n const expected = computeWebhookSignature(opts.secret, parsed.timestamp, opts.payload);\n return parsed.signatures.some((sig) => constantTimeEqual(sig, expected)) ? null : \"signature_mismatch\";\n}\n\n/** Legacy attribution-scheme inputs (`X-Wefunder-Signature: sha256=…` + `X-Wefunder-Timestamp`). */\nexport interface VerifyLegacyWebhookOptions {\n payload: RawBody;\n /** `sha256=<hex>` */\n signature: string;\n /** Unix seconds, from `X-Wefunder-Timestamp`. */\n timestamp: string | number;\n secret: string;\n toleranceSeconds?: number;\n now?: () => number;\n}\n\n/**\n * `true` iff the signature is valid and (when tolerance > 0) the timestamp is\n * within tolerance. Never throws — respond 400 without a try/catch.\n *\n * Accepts either the platform-events header (`{ header }`) or, for a legacy\n * attribution subscription, `{ signature, timestamp }`.\n */\nexport function verifyWebhook(opts: VerifyWebhookOptions | VerifyLegacyWebhookOptions): boolean {\n if (\"header\" in opts) return checkWebhookSignature(opts) === null;\n return verifyLegacyWebhook(opts);\n}\n\nfunction verifyLegacyWebhook(opts: VerifyLegacyWebhookOptions): boolean {\n const tolerance = opts.toleranceSeconds ?? DEFAULT_TOLERANCE_SECONDS;\n const ts = Number(opts.timestamp);\n if (!Number.isFinite(ts)) return false;\n if (tolerance > 0 && Math.abs((opts.now ?? Date.now)() / 1000 - ts) > tolerance) return false;\n const expected = `sha256=${computeWebhookSignature(opts.secret, opts.timestamp, opts.payload)}`;\n return constantTimeEqual(opts.signature, expected);\n}\n\n// ---------------------------------------------------------------------------\n// constructEvent — verify + parse\n// ---------------------------------------------------------------------------\n\n/** Node `IncomingHttpHeaders`, a fetch `Headers`, or a plain object. */\nexport type HeadersLike = Headers | Record<string, string | string[] | undefined>;\n\nfunction headerGetter(headers: HeadersLike | string): (name: string) => string | undefined {\n if (typeof headers === \"string\") {\n return (name) => (name === SIGNATURE_HEADER ? headers : undefined);\n }\n if (headers instanceof Headers) return (name) => headers.get(name) ?? undefined;\n // Plain objects: try the lowercase key, then a case-insensitive scan\n // (Node lowercases IncomingHttpHeaders; hand-built objects may not).\n return (name) => {\n let v = headers[name];\n if (v === undefined) {\n const hit = Object.keys(headers).find((k) => k.toLowerCase() === name);\n if (hit) v = headers[hit];\n }\n return Array.isArray(v) ? v[0] : v;\n };\n}\n\nexport interface ConstructEventOptions {\n toleranceSeconds?: number;\n now?: () => number;\n}\n\ninterface Envelope {\n id?: unknown;\n event?: unknown;\n created_at?: unknown;\n mode?: unknown;\n data?: unknown;\n}\n\n/**\n * Verify a delivery and parse its envelope in one step. Throws\n * `WebhookSignatureError` on any failure so handlers fail loudly; on success the\n * returned event is a discriminated union — narrow on `event` for typed `data`.\n *\n * @param payload the RAW request body (string or bytes) — never a re-serialized object\n * @param headers the request headers, or the `Wefunder-Signature` value itself\n * @param secret the endpoint's signing secret (shown once at create / rotate)\n */\nexport function constructEvent(\n payload: RawBody,\n headers: HeadersLike | string,\n secret: string,\n opts?: ConstructEventOptions,\n): WebhookEvent | UnknownWebhookEvent {\n const get = headerGetter(headers);\n const header = get(SIGNATURE_HEADER);\n\n if (!header) {\n const legacySig = get(LEGACY_SIGNATURE_HEADER);\n const legacyTs = get(LEGACY_TIMESTAMP_HEADER);\n if (legacySig && legacyTs) return constructLegacyEvent(payload, get, legacySig, legacyTs, secret, opts);\n throw new WebhookSignatureError(\"missing_header\", describeFailure(\"missing_header\"));\n }\n\n const failure = checkWebhookSignature({ payload, header, secret, ...opts });\n if (failure) throw new WebhookSignatureError(failure, describeFailure(failure));\n\n const parsed = parseSignatureHeader(header)!;\n const env = parseEnvelope(payload);\n return {\n id: String(env.id ?? \"\"),\n event: String(env.event ?? \"\"),\n created_at: String(env.created_at ?? \"\"),\n mode: (env.mode === \"test\" ? \"test\" : \"live\") as WebhookMode,\n data: env.data,\n timestamp: parsed.timestamp,\n } as WebhookEvent | UnknownWebhookEvent;\n}\n\nfunction constructLegacyEvent(\n payload: RawBody,\n get: (name: string) => string | undefined,\n signature: string,\n timestamp: string,\n secret: string,\n opts?: ConstructEventOptions,\n): UnknownWebhookEvent {\n if (!verifyLegacyWebhook({ payload, signature, timestamp, secret, ...opts })) {\n throw new WebhookSignatureError(\"signature_mismatch\", describeFailure(\"signature_mismatch\"));\n }\n const env = parseEnvelope(payload);\n return {\n id: String(env.id ?? get(LEGACY_DELIVERY_ID_HEADER) ?? \"\"),\n event: String(env.event ?? get(LEGACY_EVENT_HEADER) ?? \"\"),\n created_at: String(env.created_at ?? \"\"),\n mode: (env.mode === \"test\" ? \"test\" : \"live\") as WebhookMode,\n data: env.data ?? env,\n timestamp: Number(timestamp),\n };\n}\n\nfunction parseEnvelope(payload: RawBody): Envelope {\n try {\n const parsed: unknown = JSON.parse(bodyBuffer(payload).toString(\"utf8\"));\n if (parsed === null || typeof parsed !== \"object\") throw new Error(\"not an object\");\n return parsed as Envelope;\n } catch {\n throw new WebhookSignatureError(\"invalid_payload\", describeFailure(\"invalid_payload\"));\n }\n}\n\nfunction describeFailure(reason: WebhookSignatureFailure): string {\n switch (reason) {\n case \"missing_header\":\n return \"Missing Wefunder-Signature header\";\n case \"malformed_header\":\n return \"Wefunder-Signature header is malformed (expected t=<unix>,v1=<hex>)\";\n case \"timestamp_out_of_tolerance\":\n return \"Webhook timestamp is outside the replay tolerance\";\n case \"signature_mismatch\":\n return \"Webhook signature verification failed\";\n case \"invalid_payload\":\n return \"Webhook body is not a JSON object\";\n }\n}\n\n/**\n * `constructEvent` for fetch-style servers (Next.js route handlers, Hono, Remix,\n * Cloudflare Workers, Bun, Deno): reads the raw body from the `Request` for you.\n * Don't call `request.json()` first — the body must be read exactly once, as text.\n */\nexport async function constructEventFromRequest(\n request: Request,\n secret: string,\n opts?: ConstructEventOptions,\n): Promise<WebhookEvent | UnknownWebhookEvent> {\n const payload = await request.text();\n return constructEvent(payload, request.headers, secret, opts);\n}\n\n// ---------------------------------------------------------------------------\n// Dispatch — route a verified event to typed handlers\n// ---------------------------------------------------------------------------\n\nexport type WebhookHandlers = {\n [K in WebhookEventName]?: (event: WebhookEvent<K>) => void | Promise<void>;\n} & {\n /** Runs for any event with no specific handler (including names newer than this SDK). */\n default?: (event: WebhookEvent | UnknownWebhookEvent) => void | Promise<void>;\n};\n\n/**\n * Call the handler registered for `event.event`, falling back to `default`.\n * Returns `true` if a handler ran. Pairs with `constructEvent`:\n *\n * const event = constructEvent(raw, req.headers, secret);\n * await dispatchWebhook(event, {\n * \"investment.executed\": async (e) => await recordFunding(e.data),\n * default: (e) => console.log(\"unhandled\", e.event),\n * });\n */\nexport async function dispatchWebhook(\n event: WebhookEvent | UnknownWebhookEvent,\n handlers: WebhookHandlers,\n): Promise<boolean> {\n type AnyHandler = (e: never) => void | Promise<void>;\n const specific =\n event.event === \"default\"\n ? undefined\n : (handlers as Record<string, AnyHandler | undefined>)[event.event];\n if (specific) {\n await specific(event as never);\n return true;\n }\n if (handlers.default) {\n await handlers.default(event);\n return true;\n }\n return false;\n}\n"],"mappings":"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","names":["joinedValues","config","request","url"]}
|