import {z} from 'zod' export type PatchApiPublicV1ApprovalsMessagesMessageIdArgs = {messageId: string, body: {message: string, subject?: string | undefined}}; export type PatchApiPublicV1ApprovalsMessagesMessageIdOptions = {baseUrl?: string | undefined, ApiKeyAuth?: string | undefined, fetch?: typeof fetch | undefined}; export const patchApiPublicV1ApprovalsMessagesMessageIdResponse = z.object({statusCode: z.number().optional(), status: z.boolean().optional(), message: z.string().optional(), data: z.object({messageId: z.string().optional(), messageType: z.string().optional(), campaignId: z.string().optional(), prospectId: z.string().optional(), status: z.string().optional()}).optional()}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Edit the body of an unsent message draft. Works for every draft in the sequence: the first outreach message, follow-ups, and re-engagements alike. A draft stays editable while it is pending approval and after it has been approved but not yet sent (the send path reads the latest body at send time), so an approved draft can still be corrected before its send window. Once a message has been sent it can no longer be edited. An already-sent message returns 400. A 409 is reserved for the narrow case where the message is sent concurrently, after this request read its status but before the write lands. A draft stays editable after its campaign is deleted, matching the in-app behaviour. `subject` is accepted on INMAIL messages only, and cannot be blank once set. Character limits are enforced per message type: CONNECT 300 (200 on a Basic, non-Premium LinkedIn seat, and also 200 on a seat flagged as needing Sales Navigator re-authentication, where LinkedIn enforces the Basic cap even though the seat still reports Premium), INMAIL 1700 (subject 200), FOLLOW_UP 1000, RE_ENGAGEMENT 1000, FIRST_DEGREE_INTRO 8000. * * PATCH /public/v1/approvals/messages/{messageId} */ export const patchApiPublicV1ApprovalsMessagesMessageId = async (args: PatchApiPublicV1ApprovalsMessagesMessageIdArgs, options?: PatchApiPublicV1ApprovalsMessagesMessageIdOptions) => { const {baseUrl = "https://api.joinvalley.co", fetch: fetchFn = fetch, ApiKeyAuth} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (ApiKeyAuth !== undefined) headers.set("x-api-key", ApiKeyAuth) const url = `${baseUrl.replace(/\/+$/, '')}/public/v1/approvals/messages/${encodeURIComponent(String(args.messageId))}${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "PATCH", headers, body: JSON.stringify(args.body)}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(patchApiPublicV1ApprovalsMessagesMessageIdResponse, await res.json()) };