@graph8/sdk 0.7.1 → 0.11.0

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.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/core.ts","../src/forms.ts","../src/utils.ts","../src/visitors.ts","../src/copilot.ts","../src/chat.ts","../src/calendar.ts","../src/http.ts","../src/enrich.ts","../src/sequences.ts","../src/campaigns.ts","../src/integrations.ts","../src/signals.ts","../src/analytics.ts","../src/voice.ts","../src/pages.ts","../src/webhooks.ts","../src/contacts.ts","../src/companies.ts","../src/lists.ts","../src/notes.ts","../src/tasks.ts","../src/fields.ts","../src/deals.ts","../src/inbox.ts","../src/quotes.ts","../src/pipelines.ts","../src/workflows.ts","../src/skills.ts","../src/intent.ts","../src/studio.ts","../src/meetings.ts","../src/audiences.ts","../src/search.ts","../src/agency.ts","../src/marketplace.ts","../src/snippet.ts"],"sourcesContent":["export { g8 } from \"./core\";\n\n// HTTP core (B2): typed errors, automatic retries, idempotency, auto-pagination.\nexport { G8Error, request, paginate, isRetryableStatus, parseRetryAfter, backoffDelayMs } from \"./http\";\nexport type { RequestOptions, PaginatedResponse } from \"./http\";\n\n// Core types\nexport type { G8Config, G8PrivacyConfig, TrackProperties, IdentifyProperties, EnrichLookupResult } from \"./types\";\n\n// Module types\nexport type { VisitorCompany, VisitorScore } from \"./visitors\";\nexport type { CopilotConfig } from \"./copilot\";\nexport type { ChatConfig } from \"./chat\";\nexport type { CalendarConfig, TimeSlot, Booking, BookingRequest } from \"./calendar\";\nexport type { PersonEnrichment, CompanyEnrichment, EmailVerification, SearchFilter, SearchResults } from \"./enrich\";\nexport type {\n Sequence,\n AddToSequenceConfig,\n SequenceListItem,\n SequenceListParams,\n SequenceDetail,\n SequenceContactItem,\n SequenceContactsParams,\n SequenceActionResult,\n SequenceKind,\n SequenceStepType,\n SequenceStepInputType,\n SequenceStepConfig,\n SequenceChannelConfig,\n SequenceCreateParams,\n SequenceCreateResult,\n SequenceUpdateParams,\n SequenceStepUpdateParams,\n SequencePreviewStep,\n SequencePreviewChannel,\n SequencePreview,\n SequenceAnalytics,\n} from \"./sequences\";\nexport type {\n InboxChannel,\n InboxContact,\n InboxTag,\n InboxAssignee,\n InboxMessage,\n InboxThread,\n InboxListParams,\n InboxAssignResult,\n InboxTagResult,\n InboxDraft,\n InboxSendParams,\n InboxSendResult,\n} from \"./inbox\";\nexport type { Campaign, CampaignCreateConfig, CampaignStats } from \"./campaigns\";\nexport type { Integration } from \"./integrations\";\nexport type { IntentSignals } from \"./signals\";\nexport type { AnalyticsOverview } from \"./analytics\";\nexport type {\n VoiceSession,\n CallAnalysis,\n VoicePagination,\n DialerSessionSummary,\n DialerSessionsListResult,\n DialerSessionsListParams,\n DialerStatsParams,\n DialerReportFilters,\n DialerReportMetric,\n DialerStatsResult,\n DialerNumberInfo,\n DialerNumbersListResult,\n MissedCallback,\n MissedCallbacksResult,\n CallGradingResult,\n DialerAgentSummary,\n DialerAgentsListResult,\n DialerAgentsListParams,\n DialerSessionCreateParams,\n DialerSessionCreateResult,\n DialerSessionStatus,\n DialerSessionStatusUpdateResult,\n DialerSessionResumeResult,\n} from \"./voice\";\nexport type { LandingPage } from \"./pages\";\nexport type { WebhookEvent, WebhookEventPayload, ConstructEventOptions } from \"./webhooks\";\nexport { constructEvent, WebhookSignatureError, KNOWN_WEBHOOK_EVENTS } from \"./webhooks\";\nexport type {\n Contact,\n ContactListParams,\n ContactCreateParams,\n ContactUpdateParams,\n ContactColumn,\n ContactColumnCreateParams,\n} from \"./contacts\";\nexport type {\n Company,\n CompanyListParams,\n CompanyUpdateParams,\n CompanyContact,\n CompanyColumn,\n CompanyColumnCreateParams,\n} from \"./companies\";\nexport type { ContactList, ListContact } from \"./lists\";\nexport type { Note } from \"./notes\";\nexport type { Task, TaskCreateParams, TaskUpdateParams, TaskListParams } from \"./tasks\";\nexport type {\n Field,\n CreatedField,\n FieldCreateParams,\n FieldDeleteParams,\n SetFieldValueParams,\n} from \"./fields\";\nexport type {\n Deal,\n DealCreateParams,\n DealUpdateParams,\n DealListParams,\n Pipeline,\n PipelineStage,\n ContactDeal,\n PaginationMeta,\n} from \"./deals\";\nexport type {\n QuoteSummary,\n QuoteDetail,\n QuoteLineItem,\n QuoteStatus,\n QuoteCreateParams,\n QuoteUpdateParams,\n QuoteSendParams,\n QuoteListParams,\n QuotableProduct,\n QuoteSettings,\n} from \"./quotes\";\nexport type {\n StagePipeline,\n StagePipelineStage,\n StagePipelineCreateParams,\n StagePipelineUpdateParams,\n StageCreateParams,\n StageUpdateParams,\n EvidenceKey,\n PipelineSuggestion,\n} from \"./pipelines\";\nexport type {\n Workflow,\n WorkflowNode,\n WorkflowConnection,\n WorkflowConfig,\n WorkflowCreateParams,\n WorkflowUpdateParams,\n WorkflowExecution,\n WorkflowListParams,\n NodeTypeSchema,\n} from \"./workflows\";\nexport type {\n Skill,\n SkillType,\n SkillInputField,\n SkillCreateLLMParams,\n SkillCreateAPIParams,\n SkillUpdateLLMParams,\n SkillUpdateAPIParams,\n SkillTemplate,\n SkillListParams,\n} from \"./skills\";\nexport type {\n IntentKeyword,\n IntentPage,\n IntentVisitor,\n IntentCompany,\n IntentContact,\n IntentStats,\n} from \"./intent\";\nexport type {\n GlobalContextDocument,\n Persona,\n ICP,\n IntelligenceData,\n ResearchReport,\n} from \"./studio\";\nexport type {\n MeetingSummary,\n MeetingDetail,\n MeetingAttendee,\n MeetingTranscriptLine,\n MeetingAnalysis,\n MeetingListParams,\n} from \"./meetings\";\nexport type {\n AudienceSync,\n AudienceSyncPlatform,\n AudienceSyncMode,\n AudienceSyncCreateParams,\n AudienceSyncUpdateParams,\n AudienceSyncRun,\n AudienceSyncError,\n} from \"./audiences\";\nexport type {\n SearchOperator,\n SearchCondition,\n SearchParams,\n SearchSaveParams,\n SearchContactItem,\n SearchCompanyItem,\n SearchSaveResult,\n} from \"./search\";\nexport type { AgencyInfo, AgencyClient } from \"./agency\";\nexport type { MarketplaceProfile, MarketplaceOffer, MarketplaceHiring } from \"./marketplace\";\nexport type { Snippet } from \"./snippet\";\n","import { jitsuAnalytics } from \"@jitsu/js\";\nimport type { AnalyticsInterface } from \"@jitsu/js\";\nimport type { G8Config, TrackProperties, IdentifyProperties } from \"./types\";\nimport { createFormsClient } from \"./forms\";\nimport { createVisitorsClient } from \"./visitors\";\nimport { createCopilotClient } from \"./copilot\";\nimport { createChatClient } from \"./chat\";\nimport { createCalendarClient } from \"./calendar\";\nimport { createEnrichClient } from \"./enrich\";\nimport { createSequencesClient } from \"./sequences\";\nimport { createCampaignsClient } from \"./campaigns\";\nimport { createIntegrationsClient } from \"./integrations\";\nimport { createSignalsClient } from \"./signals\";\nimport { createAnalyticsClient } from \"./analytics\";\nimport { createVoiceClient } from \"./voice\";\nimport { createPagesClient } from \"./pages\";\nimport { createWebhooksClient } from \"./webhooks\";\nimport { createContactsClient } from \"./contacts\";\nimport { createCompaniesClient } from \"./companies\";\nimport { createListsClient } from \"./lists\";\nimport { createNotesClient } from \"./notes\";\nimport { createTasksClient } from \"./tasks\";\nimport { createFieldsClient } from \"./fields\";\nimport { createDealsClient } from \"./deals\";\nimport { createInboxClient } from \"./inbox\";\nimport { createQuotesClient } from \"./quotes\";\nimport { createPipelinesClient } from \"./pipelines\";\nimport { createWorkflowsClient } from \"./workflows\";\nimport { createSkillsClient } from \"./skills\";\nimport { createIntentClient } from \"./intent\";\nimport { createStudioClient } from \"./studio\";\nimport { createMeetingsClient } from \"./meetings\";\nimport { createAudiencesClient } from \"./audiences\";\nimport { createSearchClient } from \"./search\";\nimport { createAgencyClient } from \"./agency\";\nimport { createMarketplaceClient } from \"./marketplace\";\nimport { createSnippetClient } from \"./snippet\";\nimport { isServer } from \"./utils\";\n\nconst DEFAULT_HOST = \"https://t.graph8.com\";\nconst DEFAULT_API = \"https://be.graph8.com\";\n\n/**\n * graph8 SDK client.\n *\n * Handles event tracking, identity, and progressive forms.\n *\n * Usage:\n * import { g8 } from '@graph8/js';\n * g8.init({ writeKey: 'your_write_key' });\n * g8.track('page_view', { page: '/pricing' });\n * g8.identify('user@acme.com', { name: 'John', company: 'Acme' });\n */\nclass G8 {\n /** @internal */ client: AnalyticsInterface | null = null;\n /** @internal */ config: G8Config | null = null;\n /** @internal */ _forms: ReturnType<typeof createFormsClient> | null = null;\n /** @internal */ _visitors: ReturnType<typeof createVisitorsClient> | null = null;\n /** @internal */ _copilot: ReturnType<typeof createCopilotClient> | null = null;\n /** @internal */ _chat: ReturnType<typeof createChatClient> | null = null;\n /** @internal */ _calendar: ReturnType<typeof createCalendarClient> | null = null;\n /** @internal */ _enrich: ReturnType<typeof createEnrichClient> | null = null;\n /** @internal */ _sequences: ReturnType<typeof createSequencesClient> | null = null;\n /** @internal */ _campaigns: ReturnType<typeof createCampaignsClient> | null = null;\n /** @internal */ _integrations: ReturnType<typeof createIntegrationsClient> | null = null;\n /** @internal */ _signals: ReturnType<typeof createSignalsClient> | null = null;\n /** @internal */ _analytics: ReturnType<typeof createAnalyticsClient> | null = null;\n /** @internal */ _voice: ReturnType<typeof createVoiceClient> | null = null;\n /** @internal */ _pages: ReturnType<typeof createPagesClient> | null = null;\n /** @internal */ _webhooks: ReturnType<typeof createWebhooksClient> | null = null;\n /** @internal */ _contacts: ReturnType<typeof createContactsClient> | null = null;\n /** @internal */ _companies: ReturnType<typeof createCompaniesClient> | null = null;\n /** @internal */ _lists: ReturnType<typeof createListsClient> | null = null;\n /** @internal */ _notes: ReturnType<typeof createNotesClient> | null = null;\n /** @internal */ _tasks: ReturnType<typeof createTasksClient> | null = null;\n /** @internal */ _fields: ReturnType<typeof createFieldsClient> | null = null;\n /** @internal */ _deals: ReturnType<typeof createDealsClient> | null = null;\n /** @internal */ _inbox: ReturnType<typeof createInboxClient> | null = null;\n /** @internal */ _quotes: ReturnType<typeof createQuotesClient> | null = null;\n /** @internal */ _pipelines: ReturnType<typeof createPipelinesClient> | null = null;\n /** @internal */ _workflows: ReturnType<typeof createWorkflowsClient> | null = null;\n /** @internal */ _skills: ReturnType<typeof createSkillsClient> | null = null;\n /** @internal */ _intent: ReturnType<typeof createIntentClient> | null = null;\n /** @internal */ _studio: ReturnType<typeof createStudioClient> | null = null;\n /** @internal */ _meetings: ReturnType<typeof createMeetingsClient> | null = null;\n /** @internal */ _audiences: ReturnType<typeof createAudiencesClient> | null = null;\n /** @internal */ _search: ReturnType<typeof createSearchClient> | null = null;\n /** @internal */ _agency: ReturnType<typeof createAgencyClient> | null = null;\n /** @internal */ _marketplace: ReturnType<typeof createMarketplaceClient> | null = null;\n /** @internal */ _snippet: ReturnType<typeof createSnippetClient> | null = null;\n\n /**\n * Initialize the graph8 SDK. Must be called before any other method.\n * Safe to call on the server (SSR) - becomes a no-op for tracking.\n */\n init(config: G8Config): void {\n this.config = config;\n\n if (!isServer) {\n this.client = jitsuAnalytics({\n host: config.host || DEFAULT_HOST,\n writeKey: config.writeKey || \"\",\n debug: config.debug,\n });\n }\n\n const apiUrl = config.apiUrl || DEFAULT_API;\n const writeKey = config.writeKey || \"\";\n const apiKey = config.apiKey || \"\";\n\n // Public (write key) clients\n if (writeKey) {\n this._forms = createFormsClient(writeKey, apiUrl);\n this._visitors = createVisitorsClient(writeKey, apiUrl);\n this._copilot = createCopilotClient(writeKey, apiUrl);\n this._chat = createChatClient(writeKey, apiUrl);\n this._calendar = createCalendarClient(apiUrl);\n this._signals = createSignalsClient(writeKey, false, apiUrl);\n }\n\n // Private (API key) clients\n if (apiKey) {\n this._enrich = createEnrichClient(apiKey, apiUrl);\n this._sequences = createSequencesClient(apiKey, apiUrl);\n this._campaigns = createCampaignsClient(apiKey, apiUrl);\n this._integrations = createIntegrationsClient(apiKey, apiUrl);\n this._analytics = createAnalyticsClient(apiKey, apiUrl);\n this._voice = createVoiceClient(apiKey, apiUrl);\n this._pages = createPagesClient(apiKey, apiUrl);\n this._webhooks = createWebhooksClient(apiKey, apiUrl);\n this._contacts = createContactsClient(apiKey, apiUrl);\n this._companies = createCompaniesClient(apiKey, apiUrl);\n this._lists = createListsClient(apiKey, apiUrl);\n this._notes = createNotesClient(apiKey, apiUrl);\n this._tasks = createTasksClient(apiKey, apiUrl);\n this._fields = createFieldsClient(apiKey, apiUrl);\n this._deals = createDealsClient(apiKey, apiUrl);\n this._inbox = createInboxClient(apiKey, apiUrl);\n this._quotes = createQuotesClient(apiKey, apiUrl);\n this._pipelines = createPipelinesClient(apiKey, apiUrl);\n this._workflows = createWorkflowsClient(apiKey, apiUrl);\n this._skills = createSkillsClient(apiKey, apiUrl);\n this._intent = createIntentClient(apiKey, apiUrl);\n this._studio = createStudioClient(apiKey, apiUrl);\n this._meetings = createMeetingsClient(apiKey, apiUrl);\n this._audiences = createAudiencesClient(apiKey, apiUrl);\n this._search = createSearchClient(apiKey, apiUrl);\n this._agency = createAgencyClient(apiKey, apiUrl);\n this._marketplace = createMarketplaceClient(apiKey, apiUrl);\n this._snippet = createSnippetClient(apiKey, apiUrl);\n // Override signals with API key version for full access\n this._signals = createSignalsClient(apiKey, true, apiUrl);\n }\n }\n\n // -- Core tracking (via Jitsu) --\n\n /** Track a custom event. */\n track(event: string, properties?: TrackProperties): void { this.client?.track(event, properties); }\n\n /** Identify a user with properties. */\n identify(userId: string, properties?: IdentifyProperties): void { this.client?.identify(userId, properties); }\n\n /** Track a page view. */\n page(properties?: TrackProperties): void { this.client?.page(properties); }\n\n /** Clear user identity (on logout). */\n reset(): void { this.client?.reset(); }\n\n // -- Module accessors --\n\n /** Progressive form helpers. */\n get forms() { this._assertInit(); return this._forms!; }\n\n /** Visitor intelligence - IP to company, engagement scoring. */\n get visitors() { this._assertInit(); return this._visitors!; }\n\n /** AI copilot widget. */\n get copilot() { this._assertInit(); return this._copilot!; }\n\n /** Webchat widget. */\n get chat() { this._assertInit(); return this._chat!; }\n\n /** Calendar and booking. */\n get calendar() { this._assertInit(); return this._calendar!; }\n\n /** Enrichment API (requires API key). */\n get enrich() { this._assertKey(\"enrich\"); return this._enrich!; }\n\n /** Sequences (requires API key). */\n get sequences() { this._assertKey(\"sequences\"); return this._sequences!; }\n\n /** Campaigns (requires API key). */\n get campaigns() { this._assertKey(\"campaigns\"); return this._campaigns!; }\n\n /** CRM integrations (requires API key). */\n get integrations() { this._assertKey(\"integrations\"); return this._integrations!; }\n\n /** Intent signals. */\n get signals() { this._assertInit(); return this._signals!; }\n\n /** Analytics (requires API key). */\n get analytics() { this._assertKey(\"analytics\"); return this._analytics!; }\n\n /** Voice AI (requires API key). */\n get voice() { this._assertKey(\"voice\"); return this._voice!; }\n\n /** Landing pages (requires API key). */\n get pages() { this._assertKey(\"pages\"); return this._pages!; }\n\n /** Webhook event listeners (requires API key). */\n get webhooks() { this._assertKey(\"webhooks\"); return this._webhooks!; }\n\n /** Contacts CRUD (requires API key). */\n get contacts() { this._assertKey(\"contacts\"); return this._contacts!; }\n\n /** Companies CRUD (requires API key). */\n get companies() { this._assertKey(\"companies\"); return this._companies!; }\n\n /** Lists management (requires API key). */\n get lists() { this._assertKey(\"lists\"); return this._lists!; }\n\n /** Notes on contacts (requires API key). */\n get notes() { this._assertKey(\"notes\"); return this._notes!; }\n\n /** Tasks on contacts (requires API key). */\n get tasks() { this._assertKey(\"tasks\"); return this._tasks!; }\n\n /** Custom fields management (requires API key). */\n get fields() { this._assertKey(\"fields\"); return this._fields!; }\n\n /** Deals and pipelines (requires API key). */\n get deals() { this._assertKey(\"deals\"); return this._deals!; }\n\n /** Multi-channel inbox — read + reply across email, SMS, LinkedIn (requires API key). */\n get inbox() { this._assertKey(\"inbox\"); return this._inbox!; }\n\n /** Quote-to-cash: draft, send, sign, payment-link quotes (requires API key). */\n get quotes() { this._assertKey(\"quotes\"); return this._quotes!; }\n\n /** Stage Checklist v2 pipelines: workflow stages with evidence + scripts (requires API key). */\n get pipelines() { this._assertKey(\"pipelines\"); return this._pipelines!; }\n\n /** Workflow builder — multi-node automation graphs with execution lifecycle (requires API key). */\n get workflows() { this._assertKey(\"workflows\"); return this._workflows!; }\n\n /** Skill authoring — LLM and API building blocks that workflows compose (requires API key). */\n get skills() { this._assertKey(\"skills\"); return this._skills!; }\n\n /** Intent tracking — keyword groups, page visitors, account-level intent (requires API key). */\n get intent() { this._assertKey(\"intent\"); return this._intent!; }\n\n /** Studio context — ICPs, personas, brand briefs, intelligence, AI research reports (requires API key). */\n get studio() { this._assertKey(\"studio\"); return this._studio!; }\n\n /** Meetings — read scheduled, completed, cancelled meetings with transcripts + AI analysis (requires API key). */\n get meetings() { this._assertKey(\"meetings\"); return this._meetings!; }\n\n /** Audiences — sync audience lists to ad platforms (Meta, LinkedIn, Google, X) (requires API key). */\n get audiences() { this._assertKey(\"audiences\"); return this._audiences!; }\n\n /** Search — prospect open-data contacts + companies by filter, optionally save to a list (requires API key). */\n get search() { this._assertKey(\"search\"); return this._search!; }\n\n /** Agency — for agency keys: discover the agency credential + the client orgs it may target (requires API key). */\n get agency() { this._assertKey(\"agency\"); return this._agency!; }\n\n /** Marketplace — for SDR/AE talent: profile, hire offers (accept/reject), active hirings (requires API key). */\n get marketplace() { this._assertKey(\"marketplace\"); return this._marketplace!; }\n\n /** Snippet — fetch your org's tracking snippet (write key + React/script-tag embeds + config) for embedding (requires API key). */\n get snippet() { this._assertKey(\"snippet\"); return this._snippet!; }\n\n /** Whether the SDK has been initialized. */\n get initialized(): boolean { return this.config !== null; }\n\n /** @internal */\n _assertInit(): void {\n if (!this.config) throw new Error(\"g8.init() must be called first\");\n }\n\n /** @internal */\n _assertKey(module: string): void {\n this._assertInit();\n if (!this.config!.apiKey) throw new Error(`g8.${module} requires an API key. Use g8.init({ apiKey: '...' })`);\n }\n}\n\n/** Singleton g8 client instance. */\nexport const g8 = new G8();\n","import type { EnrichLookupResult } from \"./types\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\n/**\n * Progressive form enrichment - checks what fields graph8 already knows\n * about a contact so your form can skip those fields.\n *\n * Calls POST /api/v1/public/enrich/lookup (authenticated via write key).\n */\nexport const createFormsClient = (writeKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /**\n * Look up known fields for an email address.\n *\n * Use this in progressive forms: after the user enters their email,\n * check what graph8 already knows and only show missing fields.\n */\n async lookup(email: string): Promise<EnrichLookupResult> {\n const resp = await fetch(`${baseUrl}/api/v1/public/enrich/lookup`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Write-Key\": writeKey,\n },\n body: JSON.stringify({ email }),\n });\n\n if (!resp.ok) {\n return { found: false, known_fields: {}, missing_fields: [] };\n }\n\n const data = await resp.json();\n return data.data || data;\n },\n };\n};\n","/** Check if running on the server (SSR). */\nexport const isServer = typeof window === \"undefined\";\n\n/** Safely get the window object (returns undefined on server). */\nexport const getWindow = (): Window | undefined =>\n isServer ? undefined : window;\n","import type { G8Config } from \"./types\";\nimport { isServer } from \"./utils\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface VisitorCompany {\n company_name: string | null;\n company_domain: string | null;\n industry: string | null;\n employee_count: string | null;\n city: string | null;\n country: string | null;\n confidence: number;\n}\n\nexport interface VisitorScore {\n engagement: number;\n intent: \"low\" | \"medium\" | \"high\";\n signals: string[];\n}\n\ntype IntentCallback = (visitor: VisitorCompany & VisitorScore) => void;\n\n/**\n * Visitor intelligence - identify anonymous visitors by IP → company.\n *\n * Requires write key auth. Works client-side only.\n */\nexport const createVisitorsClient = (writeKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n let intentInterval: ReturnType<typeof setInterval> | null = null;\n\n const headers = () => ({\n \"Content-Type\": \"application/json\",\n \"X-Write-Key\": writeKey,\n });\n\n return {\n /** Identify the current visitor's company from their IP address. */\n async identify(): Promise<VisitorCompany> {\n if (isServer) return { company_name: null, company_domain: null, industry: null, employee_count: null, city: null, country: null, confidence: 0 };\n\n const resp = await fetch(`${baseUrl}/api/v1/public/visitors/company`, { headers: headers() });\n if (!resp.ok) return { company_name: null, company_domain: null, industry: null, employee_count: null, city: null, country: null, confidence: 0 };\n const data = await resp.json();\n return data.data || data;\n },\n\n /** Get engagement score for the current visitor. */\n async score(): Promise<VisitorScore> {\n if (isServer) return { engagement: 0, intent: \"low\", signals: [] };\n\n const resp = await fetch(`${baseUrl}/api/v1/public/visitors/score`, { headers: headers() });\n if (!resp.ok) return { engagement: 0, intent: \"low\", signals: [] };\n const data = await resp.json();\n return data.data || data;\n },\n\n /** Listen for visitors matching an intent level. Polls every 30 seconds. */\n onIntent(level: \"low\" | \"medium\" | \"high\", callback: IntentCallback): () => void {\n if (isServer) return () => {};\n\n const check = async () => {\n try {\n const [company, scoreData] = await Promise.all([\n this.identify(),\n this.score(),\n ]);\n if (scoreData.intent === level || (level === \"medium\" && scoreData.intent === \"high\")) {\n callback({ ...company, ...scoreData });\n }\n } catch { /* silent */ }\n };\n\n check();\n intentInterval = setInterval(check, 30_000);\n\n return () => {\n if (intentInterval) clearInterval(intentInterval);\n };\n },\n };\n};\n","import { isServer } from \"./utils\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface CopilotConfig {\n /** Initial greeting message */\n greeting?: string;\n /** Context passed to the AI */\n context?: Record<string, unknown>;\n /** Widget position */\n position?: \"bottom-right\" | \"bottom-left\";\n /** Widget theme */\n theme?: \"light\" | \"dark\" | \"auto\";\n}\n\ntype CopilotEvent = \"message\" | \"tool_used\" | \"open\" | \"close\" | \"error\";\ntype CopilotCallback = (data: Record<string, unknown>) => void;\ntype ActionHandler = (params: Record<string, unknown>) => void | Promise<void>;\n\n/**\n * Copilot - embeddable AI assistant with org knowledge base access.\n *\n * Client-side (write key) for the widget embed.\n */\nexport const createCopilotClient = (writeKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n const listeners: Map<CopilotEvent, CopilotCallback[]> = new Map();\n const actions: Map<string, ActionHandler> = new Map();\n let widgetEl: HTMLElement | null = null;\n\n const emit = (event: CopilotEvent, data: Record<string, unknown> = {}) => {\n listeners.get(event)?.forEach((cb) => cb(data));\n };\n\n return {\n /** Open the copilot widget. */\n open(config?: CopilotConfig): void {\n if (isServer) return;\n\n // Remove existing widget if any\n if (widgetEl) widgetEl.remove();\n\n const position = config?.position || \"bottom-right\";\n const posStyle = position === \"bottom-left\" ? \"left:16px;\" : \"right:16px;\";\n\n const iframe = document.createElement(\"iframe\");\n iframe.src = `${baseUrl}/copilot/embed?write_key=${writeKey}&theme=${config?.theme || \"auto\"}`;\n iframe.style.cssText = `position:fixed;bottom:16px;${posStyle}width:400px;height:600px;border:none;border-radius:12px;box-shadow:0 8px 32px rgba(0,0,0,0.15);z-index:99998;`;\n iframe.id = \"g8-copilot-widget\";\n\n document.body.appendChild(iframe);\n widgetEl = iframe;\n emit(\"open\");\n },\n\n /** Send a message to the copilot programmatically. */\n async ask(message: string): Promise<string> {\n const resp = await fetch(`${baseUrl}/api/v1/public/copilot/chat`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", \"X-Write-Key\": writeKey },\n body: JSON.stringify({ message }),\n });\n if (!resp.ok) return \"Sorry, I could not process that request.\";\n const data = await resp.json();\n return data.response || data.data?.response || \"\";\n },\n\n /** Register a custom action the copilot can trigger. */\n registerAction(name: string, handler: ActionHandler): void {\n actions.set(name, handler);\n },\n\n /** Listen for copilot events. */\n on(event: CopilotEvent, callback: CopilotCallback): void {\n if (!listeners.has(event)) listeners.set(event, []);\n listeners.get(event)!.push(callback);\n },\n\n /** Close the copilot widget. */\n close(): void {\n if (widgetEl) {\n widgetEl.remove();\n widgetEl = null;\n emit(\"close\");\n }\n },\n };\n};\n","import { isServer } from \"./utils\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface ChatConfig {\n /** Agent ID to connect to */\n agentId?: string;\n /** Pre-filled first message */\n message?: string;\n /** Widget position */\n position?: \"bottom-right\" | \"bottom-left\";\n /** Widget theme */\n theme?: \"light\" | \"dark\" | \"auto\";\n /** Custom greeting */\n greeting?: string;\n /** Custom avatar URL */\n avatar?: string;\n}\n\ntype ChatEvent = \"message\" | \"human_transfer\" | \"open\" | \"close\" | \"error\";\ntype ChatCallback = (data: Record<string, unknown>) => void;\n\n/**\n * Webchat - live chat + AI chat embedded in any app.\n *\n * Uses WebSocket connection to the voice/chat agent backend.\n * Public - no API key needed (org/agent IDs are in the config).\n */\nexport const createChatClient = (writeKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n const listeners: Map<ChatEvent, ChatCallback[]> = new Map();\n let widgetEl: HTMLElement | null = null;\n let ws: WebSocket | null = null;\n\n const emit = (event: ChatEvent, data: Record<string, unknown> = {}) => {\n listeners.get(event)?.forEach((cb) => cb(data));\n };\n\n return {\n /** Open the chat widget. */\n open(config?: ChatConfig): void {\n if (isServer) return;\n\n if (widgetEl) widgetEl.remove();\n\n const position = config?.position || \"bottom-right\";\n const posStyle = position === \"bottom-left\" ? \"left:16px;\" : \"right:16px;\";\n\n const iframe = document.createElement(\"iframe\");\n iframe.src = `${baseUrl}/webchat/embed?write_key=${writeKey}&theme=${config?.theme || \"auto\"}`;\n iframe.style.cssText = `position:fixed;bottom:16px;${posStyle}width:380px;height:560px;border:none;border-radius:12px;box-shadow:0 8px 32px rgba(0,0,0,0.15);z-index:99997;`;\n iframe.id = \"g8-chat-widget\";\n\n document.body.appendChild(iframe);\n widgetEl = iframe;\n emit(\"open\");\n },\n\n /** Send a message. */\n send(message: string): void {\n if (ws && ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: \"message\", content: message }));\n }\n },\n\n /** Listen for chat events. */\n on(event: ChatEvent, callback: ChatCallback): void {\n if (!listeners.has(event)) listeners.set(event, []);\n listeners.get(event)!.push(callback);\n },\n\n /** Configure the chat appearance. */\n configure(config: Partial<ChatConfig>): void {\n // Send config to iframe via postMessage\n if (widgetEl && widgetEl instanceof HTMLIFrameElement) {\n widgetEl.contentWindow?.postMessage({ type: \"g8_chat_config\", config }, \"*\");\n }\n },\n\n /** Close the chat widget. */\n close(): void {\n if (ws) { ws.close(); ws = null; }\n if (widgetEl) { widgetEl.remove(); widgetEl = null; }\n emit(\"close\");\n },\n };\n};\n","import { isServer } from \"./utils\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface CalendarConfig {\n /** Event type slug (e.g. \"demo-30min\") */\n eventType: string;\n /** Username of the host */\n username: string;\n /** Pre-fill attendee info */\n prefill?: { name?: string; email?: string; notes?: string };\n}\n\nexport interface TimeSlot {\n start: string;\n end: string;\n available: boolean;\n}\n\nexport interface Booking {\n uid: string;\n confirmation_url: string;\n start_time: string;\n end_time: string;\n}\n\nexport interface BookingRequest {\n event_type_id: number;\n slot: string;\n attendee: { name: string; email: string; notes?: string };\n}\n\ntype CalendarEvent = \"booked\" | \"cancelled\" | \"slot_selected\";\ntype CalendarCallback = (data: Record<string, unknown>) => void;\n\n/**\n * Calendar and booking - show scheduling widgets, get slots, book meetings.\n *\n * Public endpoints - no API key needed.\n */\nexport const createCalendarClient = (apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n const listeners: Map<CalendarEvent, CalendarCallback[]> = new Map();\n\n return {\n /** Show a booking modal overlay. */\n show(config: CalendarConfig): void {\n if (isServer) return;\n\n const url = `${baseUrl}/appointments/${config.username}/${config.eventType}`;\n const params = new URLSearchParams();\n if (config.prefill?.name) params.set(\"name\", config.prefill.name);\n if (config.prefill?.email) params.set(\"email\", config.prefill.email);\n\n const iframe = document.createElement(\"iframe\");\n iframe.src = `${url}?${params.toString()}`;\n iframe.style.cssText = \"position:fixed;top:0;left:0;width:100%;height:100%;border:none;z-index:99999;background:rgba(0,0,0,0.5);\";\n iframe.id = \"g8-calendar-modal\";\n document.body.appendChild(iframe);\n\n // Close on escape\n const onKey = (e: KeyboardEvent) => { if (e.key === \"Escape\") { iframe.remove(); document.removeEventListener(\"keydown\", onKey); } };\n document.addEventListener(\"keydown\", onKey);\n },\n\n /** Embed booking widget inline in a container element. */\n embed(selector: string, config: CalendarConfig): void {\n if (isServer) return;\n\n const container = document.querySelector(selector);\n if (!container) return;\n\n const url = `${baseUrl}/appointments/${config.username}/${config.eventType}`;\n const iframe = document.createElement(\"iframe\");\n iframe.src = url;\n iframe.style.cssText = \"width:100%;min-height:600px;border:none;border-radius:8px;\";\n container.appendChild(iframe);\n },\n\n /** Get available time slots for an event type. */\n async slots(username: string, eventSlug: string, range: { start: string; end: string }): Promise<TimeSlot[]> {\n const params = new URLSearchParams({\n start_date: range.start,\n end_date: range.end,\n });\n const resp = await fetch(`${baseUrl}/appointments/public/slots?username=${username}&event_slug=${eventSlug}&${params.toString()}`);\n if (!resp.ok) return [];\n const data = await resp.json();\n return data.slots || data.data || [];\n },\n\n /** Book a meeting programmatically. */\n async book(request: BookingRequest): Promise<Booking | null> {\n const resp = await fetch(`${baseUrl}/appointments/public/bookings`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(request),\n });\n if (!resp.ok) return null;\n const data = await resp.json();\n const emit = listeners.get(\"booked\");\n if (emit) emit.forEach((cb) => cb(data));\n return data;\n },\n\n /** Listen for calendar events. */\n on(event: CalendarEvent, callback: CalendarCallback): void {\n if (!listeners.has(event)) listeners.set(event, []);\n listeners.get(event)!.push(callback);\n },\n };\n};\n","/**\n * Hardened HTTP core for the graph8 JS SDK (sprint B2).\n *\n * Resource clients historically called `fetch` directly and returned\n * `resp.json()` even on a 4xx/5xx — so API errors surfaced silently as \"data\".\n * This module centralizes the request path with:\n *\n * - a typed `G8Error` (status, type, code, request_id, detail) thrown on any\n * non-2xx response, parsed from the standard ApiError envelope;\n * - automatic retry with exponential backoff + jitter on 429 and 5xx,\n * honoring the `Retry-After` header;\n * - `Idempotency-Key` support for safe POST retries (pairs with the backend\n * idempotency added in A6);\n * - a cursor `paginate()` async-iterator that follows `next_cursor` (A9).\n *\n * `fetch` and `sleep` are injectable so the retry/backoff logic is\n * deterministically unit-testable without real timers or network.\n */\n\nexport class G8Error extends Error {\n readonly status: number;\n readonly type: string;\n readonly code?: string;\n readonly requestId?: string;\n readonly detail?: unknown;\n /** True when the failure class is transient (429/5xx/network). */\n readonly retryable: boolean;\n\n constructor(args: {\n message: string;\n status: number;\n type: string;\n code?: string;\n requestId?: string;\n detail?: unknown;\n retryable?: boolean;\n }) {\n super(args.message);\n this.name = \"G8Error\";\n this.status = args.status;\n this.type = args.type;\n this.code = args.code;\n this.requestId = args.requestId;\n this.detail = args.detail;\n this.retryable = args.retryable ?? false;\n // Restore prototype chain for `instanceof` across the TS->ES5 downlevel.\n Object.setPrototypeOf(this, G8Error.prototype);\n }\n}\n\n/** 429 and 5xx are the transient classes worth retrying. */\nexport function isRetryableStatus(status: number): boolean {\n return status === 429 || (status >= 500 && status <= 599);\n}\n\n/**\n * Parse a `Retry-After` header into milliseconds. Supports both the\n * delta-seconds form (`\"2\"`) and the HTTP-date form. Returns null when absent\n * or unparseable so the caller falls back to computed backoff.\n */\nexport function parseRetryAfter(header: string | null | undefined, nowMs: number = Date.now()): number | null {\n if (!header) return null;\n const secs = Number(header);\n if (Number.isFinite(secs) && secs >= 0) return Math.round(secs * 1000);\n const dateMs = Date.parse(header);\n if (!Number.isNaN(dateMs)) {\n const delta = dateMs - nowMs;\n return delta > 0 ? delta : 0;\n }\n return null;\n}\n\n/** Exponential backoff with full jitter, capped at 10s. */\nexport function backoffDelayMs(attempt: number, baseMs = 200, rand: () => number = Math.random): number {\n const expo = Math.min(baseMs * 2 ** attempt, 10_000);\n return Math.floor(expo / 2 + rand() * (expo / 2));\n}\n\nfunction defaultSleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction buildQuery(query?: Record<string, unknown>): string {\n if (!query) return \"\";\n const qs = new URLSearchParams();\n for (const [k, v] of Object.entries(query)) {\n if (v != null) qs.set(k, String(v));\n }\n const s = qs.toString();\n return s ? `?${s}` : \"\";\n}\n\nasync function toG8Error(resp: Response): Promise<G8Error> {\n let body: unknown = undefined;\n try {\n const text = await resp.text();\n body = text ? JSON.parse(text) : undefined;\n } catch {\n body = undefined;\n }\n const env = (body ?? {}) as Record<string, unknown>;\n const message =\n (typeof env.message === \"string\" && env.message) ||\n (typeof env.error === \"string\" && env.error) ||\n `Request failed with status ${resp.status}`;\n return new G8Error({\n message,\n status: resp.status,\n type: (typeof env.type === \"string\" && env.type) || (typeof env.error === \"string\" && env.error) || \"api_error\",\n code: typeof env.code === \"string\" ? env.code : String(resp.status),\n requestId:\n (typeof env.request_id === \"string\" && env.request_id) || resp.headers.get(\"x-request-id\") || undefined,\n detail: env.detail,\n retryable: isRetryableStatus(resp.status),\n });\n}\n\nexport interface RequestOptions {\n method?: string;\n body?: unknown;\n headers?: Record<string, string>;\n query?: Record<string, unknown>;\n /** Sent as the `Idempotency-Key` header (safe POST retries; see A6). */\n idempotencyKey?: string;\n /** Max retry attempts on 429/5xx/network (default 2 -> up to 3 tries). */\n maxRetries?: number;\n /** Base backoff in ms (default 200). */\n retryBaseMs?: number;\n signal?: AbortSignal;\n /** Injected for tests; defaults to global fetch. */\n fetchImpl?: typeof fetch;\n /** Injected for tests; defaults to a real setTimeout sleep. */\n sleepImpl?: (ms: number) => Promise<void>;\n}\n\n/**\n * Perform a JSON request with retries + typed errors. Returns the parsed JSON\n * envelope (callers unwrap `.data` as today). Throws `G8Error` on any non-2xx\n * after exhausting retries.\n */\nexport async function request<T = unknown>(\n baseUrl: string,\n path: string,\n apiKey: string,\n opts: RequestOptions = {},\n): Promise<T> {\n const {\n method = \"GET\",\n body,\n headers = {},\n query,\n idempotencyKey,\n maxRetries = 2,\n retryBaseMs = 200,\n signal,\n fetchImpl = fetch,\n sleepImpl = defaultSleep,\n } = opts;\n\n const url = baseUrl.replace(/\\/+$/, \"\") + path + buildQuery(query);\n const finalHeaders: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n ...headers,\n };\n if (idempotencyKey) finalHeaders[\"Idempotency-Key\"] = idempotencyKey;\n\n let attempt = 0;\n for (;;) {\n let resp: Response;\n try {\n resp = await fetchImpl(url, {\n method,\n headers: finalHeaders,\n body: body == null ? undefined : JSON.stringify(body),\n signal,\n });\n } catch (err) {\n if (attempt < maxRetries) {\n await sleepImpl(backoffDelayMs(attempt, retryBaseMs));\n attempt++;\n continue;\n }\n throw new G8Error({\n message: `Network error: ${(err as Error)?.message ?? \"request failed\"}`,\n status: 0,\n type: \"network_error\",\n retryable: true,\n });\n }\n\n if (resp.ok) {\n const text = await resp.text();\n return (text ? JSON.parse(text) : undefined) as T;\n }\n\n if (isRetryableStatus(resp.status) && attempt < maxRetries) {\n const retryAfter = parseRetryAfter(resp.headers.get(\"retry-after\"));\n const delay = retryAfter != null ? retryAfter : backoffDelayMs(attempt, retryBaseMs);\n await sleepImpl(delay);\n attempt++;\n continue;\n }\n\n throw await toG8Error(resp);\n }\n}\n\nexport interface PaginatedResponse<T> {\n data: T[];\n pagination?: { next_cursor?: string | null; has_next?: boolean; page?: number };\n}\n\n/**\n * Auto-pagination async iterator following `next_cursor` (A9). Yields every\n * item across pages so callers can `for await (const x of paginate(...))`\n * without manual cursor bookkeeping.\n */\nexport async function* paginate<T>(\n fetchPage: (cursor?: string) => Promise<PaginatedResponse<T>>,\n): AsyncGenerator<T, void, unknown> {\n let cursor: string | undefined = undefined;\n for (;;) {\n const page = await fetchPage(cursor);\n for (const item of page.data ?? []) yield item;\n const next = page.pagination?.next_cursor;\n if (!next) break;\n cursor = next;\n }\n}\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface PersonEnrichment {\n found: boolean;\n confidence: number;\n data: Record<string, unknown>;\n}\n\nexport interface CompanyEnrichment {\n found: boolean;\n confidence: number;\n data: Record<string, unknown>;\n}\n\nexport interface EmailVerification {\n email: string;\n valid: boolean;\n deliverable: boolean;\n catch_all: boolean;\n}\n\nexport interface SearchFilter {\n field: string;\n operator: \"any_of\" | \"contains\" | \"all_of\" | \"none_of\" | \"is_empty\" | \"is_not_empty\" | \"between\" | \"exists\";\n value: unknown;\n}\n\nexport interface SearchResults {\n contacts: Record<string, unknown>[];\n total: number;\n page: number;\n}\n\n/**\n * Enrichment API - person/company lookup, email verification, prospecting search.\n *\n * Requires API key (server-side only). Credits charged per call. On the hardened\n * HTTP core: throws a typed `G8Error` on failure and retries transient errors.\n */\nexport const createEnrichClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** Look up a person by email, LinkedIn, or name + company. Costs 1 credit. */\n async person(params: {\n email?: string;\n linkedin_url?: string;\n first_name?: string;\n last_name?: string;\n company_domain?: string;\n }): Promise<PersonEnrichment> {\n const resp = await request<{ data?: PersonEnrichment }>(baseUrl, \"/api/v1/enrichment/lookup/person\", apiKey, {\n method: \"POST\",\n body: params,\n });\n return resp.data ?? (resp as unknown as PersonEnrichment);\n },\n\n /** Look up a company by domain or name. Costs 1 credit. */\n async company(params: { domain?: string; name?: string }): Promise<CompanyEnrichment> {\n const resp = await request<{ data?: CompanyEnrichment }>(baseUrl, \"/api/v1/enrichment/lookup/company\", apiKey, {\n method: \"POST\",\n body: params,\n });\n return resp.data ?? (resp as unknown as CompanyEnrichment);\n },\n\n /** Verify an email address. Costs 1 credit. */\n async verifyEmail(email: string): Promise<EmailVerification> {\n const resp = await request<{ data?: EmailVerification }>(baseUrl, \"/api/v1/enrichment/verify-email\", apiKey, {\n method: \"POST\",\n body: { email },\n });\n return resp.data ?? (resp as unknown as EmailVerification);\n },\n\n /** Search 300M+ contacts with filters. Credits charged per result. */\n async search(filters: SearchFilter[], page = 1, limit = 25): Promise<SearchResults> {\n const resp = await request<{ data?: SearchResults }>(baseUrl, \"/api/v1/search/contacts\", apiKey, {\n method: \"POST\",\n body: { filters, page, limit },\n });\n return resp.data ?? (resp as unknown as SearchResults);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\n// -- Existing types (preserved for backwards compat) --\n\nexport interface Sequence {\n id: string;\n name: string;\n status: string;\n step_count: number | null;\n contact_count: number | null;\n}\n\nexport interface AddToSequenceConfig {\n sequenceId: string;\n contactIds: number[];\n listId: number;\n}\n\n// -- New (0.4.0) types --\n\nexport interface SequenceListItem {\n id: string;\n name: string | null;\n status: string | null;\n user_email: string | null;\n step_count: number | null;\n contact_count: number | null;\n sequence_kind: string | null;\n associated_list_id: number | null;\n created_at: string | null;\n updated_at: string | null;\n}\n\nexport interface SequenceListParams {\n page?: number;\n limit?: number;\n /** Filter by sequence status (e.g. \"live\", \"draft\", \"paused\"). */\n status?: string;\n /** Filter by sequence kind (\"cold_outbound\" or \"nurture\"). Omit to list all kinds. */\n sequence_kind?: SequenceKind;\n}\n\nexport interface SequenceDetail {\n id: string;\n name: string | null;\n description: string | null;\n status: string | null;\n user_email: string | null;\n associated_list_id: number | null;\n finish_on_reply: boolean;\n send_in_same_thread: boolean;\n wait_for_new_contacts: boolean;\n paused_at: string | null;\n resumed_at: string | null;\n /** Sequence kind. Immutable after creation. \"cold_outbound\" (default) or \"nurture\". */\n sequence_kind?: string | null;\n /** Pinned mailbox for nurture sequences; null for cold_outbound. Immutable. */\n pinned_mailbox_id?: number | null;\n created_at: string | null;\n updated_at: string | null;\n}\n\nexport interface SequenceContactItem {\n id: string | null;\n contact_id: number | null;\n state: string | null;\n current_step_order: number | null;\n created_at: string | null;\n updated_at: string | null;\n}\n\nexport interface SequenceContactsParams {\n page?: number;\n limit?: number;\n /** Filter by contact state (e.g. \"active\", \"completed\", \"replied\"). */\n state?: string;\n}\n\nexport interface SequenceActionResult {\n sequence_id: string;\n status: string;\n contacts_affected: number;\n}\n\n/**\n * Step type. Note: LinkedIn flows use \"HEYREACH\" — there is no \"LINKEDIN\" step type.\n * Server is case-insensitive on input but stores uppercase.\n */\nexport type SequenceStepType =\n | \"EMAIL\"\n | \"PHONE\"\n | \"SMS\"\n | \"WHATSAPP\"\n | \"HEYREACH\"\n | \"MANUAL_DIALER\";\n\nexport type SequenceStepInputType =\n | \"ON_DEMAND\"\n | \"MANUAL_TEMPLATE\"\n | \"AI_GENERATED_TEMPLATE\";\n\nexport interface SequenceStepConfig {\n step_order: number;\n step_type: SequenceStepType | string;\n /** Defaults to \"ON_DEMAND\". */\n input_type?: SequenceStepInputType | string;\n /** Wait time before this step in seconds. Defaults to 0. */\n time_interval?: number;\n /** Template body, AI prompt, or other step-type-specific config. */\n step_data?: Record<string, unknown>;\n}\n\nexport interface SequenceChannelConfig {\n channel_id: number;\n channel_value: string;\n channel_type: string;\n channel_data?: Record<string, unknown>;\n}\n\n/**\n * Sequence kind. A \"nurture\" is an ordinary sequence with `sequence_kind:\n * \"nurture\"` — same step types as cold outreach, but pinned to a single mailbox\n * with a higher daily email cap. There is no separate nurture client; create one\n * via `sequences.create({ sequence_kind: \"nurture\", pinned_mailbox_id })`.\n */\nexport type SequenceKind = \"cold_outbound\" | \"nurture\";\n\nexport interface SequenceCreateParams {\n name: string;\n user_email: string;\n description?: string;\n finish_on_reply?: boolean;\n send_in_same_thread?: boolean;\n wait_for_new_contacts?: boolean;\n associated_list_id?: number;\n steps?: SequenceStepConfig[];\n channels?: SequenceChannelConfig[];\n campaign_id?: string;\n /**\n * Sequence kind. Defaults to \"cold_outbound\" server-side. Immutable after\n * creation. \"nurture\" requires `pinned_mailbox_id` and is gated by the\n * ENABLE_NURTURE feature flag.\n */\n sequence_kind?: SequenceKind;\n /**\n * Mailbox to pin for a nurture sequence. Required when\n * `sequence_kind: \"nurture\"`; all email channels must use this mailbox.\n * Ignored for cold_outbound sequences.\n */\n pinned_mailbox_id?: number;\n}\n\nexport interface SequenceCreateResult {\n id: string;\n name: string;\n status: string;\n created_at: string | null;\n}\n\nexport interface SequenceUpdateParams {\n name?: string;\n description?: string;\n is_shared?: boolean;\n finish_on_reply?: boolean;\n send_in_same_thread?: boolean;\n wait_for_new_contacts?: boolean;\n schedule_id?: string;\n appointment_id?: number;\n}\n\nexport interface SequenceStepUpdateParams {\n step_data?: Record<string, unknown>;\n time_interval?: number;\n step_type?: SequenceStepType | string;\n input_type?: SequenceStepInputType | string;\n}\n\nexport interface SequencePreviewStep {\n id: string;\n step_order: number;\n step_type: string;\n input_type: string;\n time_interval: number | null;\n step_data: Record<string, unknown> | null;\n}\n\nexport interface SequencePreviewChannel {\n id: string;\n channel_id: number | null;\n channel_value: string | null;\n channel_type: string | null;\n}\n\nexport interface SequencePreview {\n id: string;\n name: string | null;\n status: string | null;\n description: string | null;\n steps: SequencePreviewStep[];\n channels: SequencePreviewChannel[];\n}\n\nexport interface SequenceAnalytics {\n overview: Record<string, unknown>;\n performance: Record<string, unknown>;\n engagement: Record<string, unknown>;\n timeline: Record<string, unknown>[];\n contact_distribution: Record<string, unknown>;\n step_breakdown: Record<string, unknown>[];\n step_creation_methods: Record<string, unknown>[];\n sender_distribution: Record<string, unknown>[];\n}\n\nexport interface PaginationMeta {\n page: number;\n limit: number;\n total: number;\n has_next: boolean;\n}\n\n/**\n * Sequences API — list, create, run, pause, update, analyze multi-channel sequences.\n * Requires API key (server-side).\n *\n * Backed by:\n * GET /api/v1/sequences\n * POST /api/v1/sequences\n * GET /api/v1/sequences/{sequence_id}\n * PATCH /api/v1/sequences/{sequence_id}\n * DELETE /api/v1/sequences/{sequence_id}\n * GET /api/v1/sequences/{sequence_id}/contacts\n * POST /api/v1/sequences/{sequence_id}/contacts\n * POST /api/v1/sequences/{sequence_id}/run\n * POST /api/v1/sequences/{sequence_id}/pause\n * POST /api/v1/sequences/{sequence_id}/resume\n * PATCH /api/v1/sequences/{sequence_id}/steps/{step_id}\n * GET /api/v1/sequences/{sequence_id}/preview\n * GET /api/v1/sequences/{sequence_id}/analytics\n */\nexport const createSequencesClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n // -- Overloads on list() preserve backwards compat with v0.3.0's positional signature --\n\n async function list(): Promise<SequenceListItem[]>;\n async function list(page: number, limit?: number): Promise<SequenceListItem[]>;\n async function list(params: SequenceListParams): Promise<SequenceListItem[]>;\n async function list(\n pageOrParams?: number | SequenceListParams,\n limit?: number,\n ): Promise<SequenceListItem[]> {\n let params: SequenceListParams;\n if (typeof pageOrParams === \"number\") {\n params = { page: pageOrParams, limit: limit ?? 50 };\n } else {\n params = pageOrParams ?? {};\n }\n const resp = await request<{ data?: SequenceListItem[] }>(baseUrl, \"/api/v1/sequences\", apiKey, {\n query: params as Record<string, unknown>,\n });\n return (resp.data ?? (resp as unknown as SequenceListItem[])) as SequenceListItem[];\n }\n\n return {\n /** List sequences with pagination + optional status filter. */\n list,\n\n /** Get full sequence details by ID. */\n async get(sequenceId: string): Promise<SequenceDetail> {\n const resp = await request<{ data?: SequenceDetail }>(baseUrl, `/api/v1/sequences/${sequenceId}`, apiKey);\n return resp.data ?? (resp as unknown as SequenceDetail);\n },\n\n /** List contacts enrolled in a sequence. Filter by state (e.g. \"active\", \"replied\"). */\n async contacts(\n sequenceId: string,\n params: SequenceContactsParams = {},\n ): Promise<{ data: SequenceContactItem[]; pagination?: PaginationMeta }> {\n return request(baseUrl, `/api/v1/sequences/${sequenceId}/contacts`, apiKey, {\n query: params as Record<string, unknown>,\n });\n },\n\n /** Add contacts to a sequence (V2 queuing). Live or drafted sequences only. */\n async add(config: AddToSequenceConfig): Promise<SequenceActionResult> {\n const resp = await request<{ data?: SequenceActionResult }>(\n baseUrl,\n `/api/v1/sequences/${config.sequenceId}/contacts`,\n apiKey,\n { method: \"POST\", body: { contact_ids: config.contactIds, list_id: config.listId } },\n );\n return resp.data ?? (resp as unknown as SequenceActionResult);\n },\n\n /** Create a new sequence with optional steps + channels. */\n async create(payload: SequenceCreateParams): Promise<SequenceCreateResult> {\n const resp = await request<{ data?: SequenceCreateResult }>(baseUrl, \"/api/v1/sequences\", apiKey, {\n method: \"POST\",\n body: payload,\n });\n return resp.data ?? (resp as unknown as SequenceCreateResult);\n },\n\n /** Update sequence metadata. Rejected (409) if sequence is in a transitional status. */\n async update(sequenceId: string, fields: SequenceUpdateParams): Promise<SequenceActionResult> {\n const resp = await request<{ data?: SequenceActionResult }>(baseUrl, `/api/v1/sequences/${sequenceId}`, apiKey, {\n method: \"PATCH\",\n body: fields,\n });\n return resp.data ?? (resp as unknown as SequenceActionResult);\n },\n\n /** Update a single step within a sequence. */\n async updateStep(\n sequenceId: string,\n stepId: string,\n fields: SequenceStepUpdateParams,\n ): Promise<SequenceActionResult> {\n const resp = await request<{ data?: SequenceActionResult }>(\n baseUrl,\n `/api/v1/sequences/${sequenceId}/steps/${stepId}`,\n apiKey,\n { method: \"PATCH\", body: fields },\n );\n return resp.data ?? (resp as unknown as SequenceActionResult);\n },\n\n /** Soft-delete (archive) a sequence. */\n async delete(sequenceId: string): Promise<SequenceActionResult> {\n const resp = await request<{ data?: SequenceActionResult }>(baseUrl, `/api/v1/sequences/${sequenceId}`, apiKey, {\n method: \"DELETE\",\n });\n return resp.data ?? (resp as unknown as SequenceActionResult);\n },\n\n /** Run/start a DRAFTED sequence (V2 orchestration). */\n async run(sequenceId: string): Promise<SequenceActionResult> {\n const resp = await request<{ data?: SequenceActionResult }>(\n baseUrl,\n `/api/v1/sequences/${sequenceId}/run`,\n apiKey,\n { method: \"POST\" },\n );\n return resp.data ?? (resp as unknown as SequenceActionResult);\n },\n\n /** Pause a live sequence. */\n async pause(sequenceId: string): Promise<SequenceActionResult> {\n const resp = await request<{ data?: SequenceActionResult }>(\n baseUrl,\n `/api/v1/sequences/${sequenceId}/pause`,\n apiKey,\n { method: \"POST\" },\n );\n return resp.data ?? (resp as unknown as SequenceActionResult);\n },\n\n /** Resume a paused sequence. */\n async resume(sequenceId: string): Promise<SequenceActionResult> {\n const resp = await request<{ data?: SequenceActionResult }>(\n baseUrl,\n `/api/v1/sequences/${sequenceId}/resume`,\n apiKey,\n { method: \"POST\" },\n );\n return resp.data ?? (resp as unknown as SequenceActionResult);\n },\n\n /** Read-only sequence preview with all steps + channels (no enrollment). */\n async preview(sequenceId: string): Promise<SequencePreview> {\n const resp = await request<{ data?: SequencePreview }>(baseUrl, `/api/v1/sequences/${sequenceId}/preview`, apiKey);\n return resp.data ?? (resp as unknown as SequencePreview);\n },\n\n /** Comprehensive analytics for a sequence. */\n async analytics(sequenceId: string): Promise<SequenceAnalytics> {\n const resp = await request<{ data?: SequenceAnalytics }>(\n baseUrl,\n `/api/v1/sequences/${sequenceId}/analytics`,\n apiKey,\n );\n return resp.data ?? (resp as unknown as SequenceAnalytics);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface Campaign {\n id: string;\n name: string;\n slug: string;\n status: string;\n category: string | null;\n goal: string | null;\n target_persona: string | null;\n}\n\nexport interface CampaignCreateConfig {\n name: string;\n category?: string;\n brief?: string;\n core_concept?: string;\n primary_hook?: string;\n target_persona?: string;\n goal?: string;\n}\n\nexport interface CampaignStats {\n sent: number;\n opened: number;\n replied: number;\n meetings: number;\n}\n\n/**\n * Campaigns - create, manage, launch campaigns. Requires API key (server-side).\n * On the hardened HTTP core: throws a typed `G8Error` on failure and retries\n * transient errors.\n */\nexport const createCampaignsClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n async list(page = 1, limit = 50): Promise<Campaign[]> {\n const resp = await request<{ data?: Campaign[] }>(baseUrl, \"/api/v1/campaigns\", apiKey, {\n query: { page, limit },\n });\n return resp.data ?? (resp as unknown as Campaign[]);\n },\n\n async get(campaignId: string): Promise<Campaign> {\n const resp = await request<{ data?: Campaign }>(baseUrl, `/api/v1/campaigns/${campaignId}`, apiKey);\n return resp.data ?? (resp as unknown as Campaign);\n },\n\n async create(config: CampaignCreateConfig): Promise<Campaign> {\n const resp = await request<{ data?: Campaign }>(baseUrl, \"/api/v1/campaigns\", apiKey, {\n method: \"POST\",\n body: config,\n });\n return resp.data ?? (resp as unknown as Campaign);\n },\n\n async launch(campaignId: string): Promise<void> {\n await request(baseUrl, `/api/v1/campaigns/${campaignId}/launch`, apiKey, { method: \"POST\" });\n },\n\n async stats(campaignId: string): Promise<CampaignStats> {\n const resp = await request<{ data?: CampaignStats }>(baseUrl, `/api/v1/campaigns/${campaignId}/stats`, apiKey);\n return resp.data ?? (resp as unknown as CampaignStats);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface Integration {\n id: string;\n provider: string;\n status: string;\n connected_at: string | null;\n}\n\n/**\n * Integrations - connect CRM platforms, trigger syncs. Requires API key\n * (server-side). On the hardened HTTP core: throws a typed `G8Error` on failure\n * and retries transient errors.\n */\nexport const createIntegrationsClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n async list(): Promise<Integration[]> {\n const resp = await request<{ data?: Integration[] }>(baseUrl, \"/api/v1/integrations\", apiKey);\n return resp.data ?? (resp as unknown as Integration[]);\n },\n\n async connect(provider: string, config?: Record<string, unknown>): Promise<void> {\n await request(baseUrl, \"/api/v1/integrations/connect\", apiKey, {\n method: \"POST\",\n body: { provider, ...config },\n });\n },\n\n async sync(provider: string, config?: { direction?: \"inbound\" | \"outbound\" | \"bidirectional\" }): Promise<void> {\n await request(baseUrl, \"/api/v1/integrations/sync\", apiKey, {\n method: \"POST\",\n body: { provider, ...config },\n });\n },\n };\n};\n","const DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface IntentSignals {\n domain: string;\n score: number;\n intent: \"low\" | \"medium\" | \"high\";\n signals: string[];\n last_seen: string | null;\n}\n\n/**\n * Intent signals - company-level buying signals. Write key for public, API key for full access.\n */\nexport const createSignalsClient = (key: string, isApiKey: boolean, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n const headers = (): Record<string, string> => isApiKey\n ? { \"Content-Type\": \"application/json\", \"Authorization\": `Bearer ${key}` }\n : { \"Content-Type\": \"application/json\", \"X-Write-Key\": key };\n\n const endpoint = isApiKey ? \"/api/v1/signals/company\" : \"/api/v1/public/signals/company\";\n\n return {\n /** Get intent signals for a specific company domain. */\n async company(domain: string): Promise<IntentSignals> {\n const resp = await fetch(`${baseUrl}${endpoint}?domain=${encodeURIComponent(domain)}`, { headers: headers() });\n if (!resp.ok) return { domain, score: 0, intent: \"low\", signals: [], last_seen: null };\n const data = await resp.json();\n return data.data || data;\n },\n\n /** Stream intent signals - calls callback every 30s with latest data. */\n stream(domains: string[], callback: (signals: IntentSignals[]) => void): () => void {\n const check = async () => {\n try {\n const results = await Promise.all(domains.map((d) => this.company(d)));\n callback(results);\n } catch { /* silent */ }\n };\n\n check();\n const interval = setInterval(check, 30_000);\n return () => clearInterval(interval);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface AnalyticsOverview {\n visitors: number;\n contacts_created: number;\n emails_sent: number;\n emails_opened: number;\n replies: number;\n meetings_booked: number;\n period: string;\n}\n\n/**\n * Analytics - dashboard data and metrics. Requires API key (server-side).\n *\n * On the hardened HTTP core: throws a typed `G8Error` on failure and retries\n * transient errors. Note the deliberate behavior change vs the preview client —\n * a non-2xx response now **throws** instead of silently returning an all-zeros\n * overview, so callers can distinguish genuinely-zero activity from an auth/5xx\n * failure.\n */\nexport const createAnalyticsClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n async overview(config?: { period?: string; metrics?: string[] }): Promise<AnalyticsOverview> {\n const resp = await request<{ data?: AnalyticsOverview }>(baseUrl, \"/api/v1/analytics/overview\", apiKey, {\n query: { period: config?.period },\n });\n return resp.data ?? (resp as unknown as AnalyticsOverview);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\n// -- Existing (preview) types — preserved for backwards compat with v0.3.0 --\n\nexport interface VoiceSession {\n id: string;\n status: string;\n agent: string;\n started_at: string;\n}\n\nexport interface CallAnalysis {\n duration_seconds: number;\n sentiment: \"positive\" | \"neutral\" | \"negative\";\n summary: string;\n next_steps: string[];\n objections: string[];\n transcript: Array<{ speaker: string; text: string; timestamp: number }>;\n}\n\ntype VoiceEvent = \"connected\" | \"transcription\" | \"ended\" | \"error\";\ntype VoiceCallback = (data: Record<string, unknown>) => void;\n\n// -- New (0.4.0) dialer types — backed by /api/v1/voice/dialer/* --\n\nexport interface VoicePagination {\n total_items: number;\n total_pages: number;\n current_page: number;\n page_size: number;\n}\n\nexport interface DialerSessionSummary {\n session_id: string;\n status: string | null;\n user_id: string | null;\n user_email: string | null;\n org_id: string | null;\n from_phone: string | null;\n campaign_id: string | null;\n campaign_builder_campaign_id: string | null;\n name: string | null;\n session_metadata: Record<string, unknown> | null;\n total_calls: number | null;\n created_at: string | null;\n updated_at: string | null;\n contact_ids: unknown[];\n}\n\nexport interface DialerSessionsListResult {\n sessions: DialerSessionSummary[];\n pagination: VoicePagination;\n}\n\nexport interface DialerSessionsListParams {\n page?: number;\n /** Default 50, max 200. */\n page_size?: number;\n /** Comma-separated status list (e.g. \"ACTIVE,PAUSED\"). */\n status?: string;\n user_email?: string;\n /** Substring search on session name. */\n name?: string;\n campaign_id?: string;\n list_id?: string;\n list_name?: string;\n /** ISO 8601 timestamp. */\n date_from?: string;\n /** ISO 8601 timestamp. */\n date_to?: string;\n sort_by?: string;\n /** Default \"desc\". */\n sort_order?: \"asc\" | \"desc\";\n}\n\nexport interface DialerStatsParams {\n session_id?: string;\n user_email?: string;\n /** YYYY-MM-DD. */\n date_from?: string;\n /** YYYY-MM-DD. */\n date_to?: string;\n /** Default \"DAILY\". */\n aggregation?: \"DAILY\" | \"TOTAL\";\n}\n\nexport interface DialerReportFilters {\n session_id: string | null;\n user_email: string | null;\n org_id: string | null;\n date_from: string | null;\n date_to: string | null;\n aggregation: string | null;\n}\n\nexport interface DialerReportMetric {\n date: string | null;\n sdr_name: string | null;\n org_id: string | null;\n list_title: string | null;\n total_dials: number;\n total_connections: number;\n connection_rate: number;\n total_voicemails: number;\n voicemail_rate: number;\n talk_time_minutes: number;\n avg_call_duration_minutes: number;\n dispositions: Record<string, unknown> | null;\n success_rate: number;\n unique_sessions: number;\n avg_calls_per_session: number;\n redial_count: number;\n redial_success_rate: number | null;\n peak_calling_hour: number | null;\n total_callbacks: number;\n}\n\nexport interface DialerStatsResult {\n filters: DialerReportFilters;\n metrics: DialerReportMetric[];\n summary: DialerReportMetric | null;\n}\n\nexport interface DialerNumberInfo {\n number: string;\n /** Default \"ai\". */\n inbound_type: string;\n /** Default \"twilio\". */\n telephony_provider: string;\n calls_today: number;\n calls_7d: number;\n connect_rate_7d: number;\n is_valid: boolean;\n daily_limit: number;\n assigned_to: string | null;\n created_at: string | null;\n}\n\nexport interface DialerNumbersListResult {\n numbers: DialerNumberInfo[];\n}\n\nexport interface MissedCallback {\n id: string | number | null;\n caller_phone: string | null;\n inbound_number: string | null;\n first_name: string | null;\n last_name: string | null;\n email: string | null;\n contact_id: string | number | null;\n parallel_session_id: string | null;\n created_at: string | null;\n call_duration: number | null;\n is_callback: boolean;\n}\n\nexport interface MissedCallbacksResult {\n missed_callbacks: MissedCallback[];\n count: number;\n}\n\nexport interface CallGradingResult {\n room_name: string;\n /** \"ready\" or \"pending\". */\n status: string;\n grading: Record<string, unknown> | null;\n reviewed: boolean;\n reviewed_at: string | null;\n}\n\nexport interface DialerAgentSummary {\n agent_id: string;\n agent_name: string | null;\n /** \"SDR\", etc. */\n role: string | null;\n agent_status: string | null;\n /** \"agent\" or \"twin\". */\n entity_type: string | null;\n description: string | null;\n phone: string | null;\n is_template: boolean;\n}\n\nexport interface DialerAgentsListResult {\n agents: DialerAgentSummary[];\n total_count: number;\n}\n\nexport interface DialerAgentsListParams {\n /** e.g. \"SDR\". */\n role?: string;\n agent_status?: string;\n /** \"agent\" or \"twin\". */\n entity_type?: \"agent\" | \"twin\";\n /** Substring filter on name/description. */\n search?: string;\n}\n\nexport interface DialerSessionCreateParams {\n /** 1-200 chars. */\n name: string;\n /** Org's dialer phone (E.164, 9-16 chars). */\n from_phone: string;\n /** Contact list ID (stored in session metadata). */\n list_id?: string;\n /** Display title for the source list. */\n list_title?: string;\n /** V2 agent UUID. */\n agent_id?: string;\n /** V1 fallback name. Defaults to \"default_agent\". */\n agent_name?: string;\n /** \"agent\" or \"twin\". */\n entity_type?: \"agent\" | \"twin\";\n /** Campaign Builder UUID. */\n studio_campaign_id?: string;\n /** IANA timezone (e.g. \"America/New_York\"). */\n user_timezone?: string;\n /** Per-session voicemail-skip override. null/omit = use SDR default. */\n skip_voicemails?: boolean;\n}\n\nexport interface DialerSessionCreateResult {\n session_id: string;\n status: string;\n name: string | null;\n org_id: string | null;\n user_id: string | null;\n user_email: string | null;\n from_phone: string | null;\n session_metadata: Record<string, unknown> | null;\n total_calls: number;\n created_at: string | null;\n message: string | null;\n}\n\n/** \"ACTIVE\" resumes, \"PAUSED\" pauses, \"COMPLETED\" stops. \"FAILED\" is rejected. */\nexport type DialerSessionStatus = \"ACTIVE\" | \"PAUSED\" | \"COMPLETED\";\n\nexport interface DialerSessionStatusUpdateResult {\n session_id: string;\n status: string;\n message: string | null;\n name: string | null;\n org_id: string | null;\n user_id: string | null;\n user_email: string | null;\n from_phone: string | null;\n session_metadata: Record<string, unknown> | null;\n total_calls: number;\n created_at: string | null;\n updated_at: string | null;\n}\n\nexport interface DialerSessionResumeResult extends DialerSessionStatusUpdateResult {\n /** Contacts actually placed in this batch (voice caps at 4). */\n dialed_count: number;\n}\n\n/**\n * Voice AI — start AI voice calls, get transcriptions and analysis.\n * Plus full parallel-dialer session control via the `dialer` namespace.\n * Requires API key (server-side).\n *\n * Backed by:\n * GET /api/v1/voice/dialer/sessions\n * POST /api/v1/voice/dialer/sessions\n * PATCH /api/v1/voice/dialer/sessions/{session_id}/status\n * POST /api/v1/voice/dialer/sessions/{session_id}/resume\n * GET /api/v1/voice/dialer/stats\n * GET /api/v1/voice/dialer/numbers\n * GET /api/v1/voice/dialer/missed-callbacks\n * GET /api/v1/voice/dialer/calls/{room_name}/grading\n * GET /api/v1/voice/dialer/agents\n */\nexport const createVoiceClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n const listeners: Map<VoiceEvent, VoiceCallback[]> = new Map();\n\n const dialer = {\n /** List parallel-dialer sessions with filters + pagination. */\n async listSessions(params: DialerSessionsListParams = {}): Promise<DialerSessionsListResult> {\n const resp = await request<{ data?: DialerSessionsListResult }>(\n baseUrl,\n \"/api/v1/voice/dialer/sessions\",\n apiKey,\n { query: params as Record<string, unknown> },\n );\n return resp.data ?? (resp as unknown as DialerSessionsListResult);\n },\n\n /** Create a parallel-dialer session in PAUSED state. SDR opens UI to start dialing. */\n async createSession(payload: DialerSessionCreateParams): Promise<DialerSessionCreateResult> {\n const resp = await request<{ data?: DialerSessionCreateResult }>(\n baseUrl,\n \"/api/v1/voice/dialer/sessions\",\n apiKey,\n { method: \"POST\", body: payload },\n );\n return resp.data ?? (resp as unknown as DialerSessionCreateResult);\n },\n\n /** Pause / resume / stop a dialer session via status flip. */\n async updateSessionStatus(\n sessionId: string,\n status: DialerSessionStatus,\n ): Promise<DialerSessionStatusUpdateResult> {\n const resp = await request<{ data?: DialerSessionStatusUpdateResult }>(\n baseUrl,\n `/api/v1/voice/dialer/sessions/${sessionId}/status`,\n apiKey,\n { method: \"PATCH\", body: { status } },\n );\n return resp.data ?? (resp as unknown as DialerSessionStatusUpdateResult);\n },\n\n /**\n * Resume a PAUSED dialer session. Auto-fetches the next batch from the source list,\n * filters already-called + phoneless rows, and forwards to voice's start-session.\n * @param maxContacts 1-4 (voice caps parallel dialing at 4). Default 4.\n */\n async resumeSession(sessionId: string, maxContacts = 4): Promise<DialerSessionResumeResult> {\n const resp = await request<{ data?: DialerSessionResumeResult }>(\n baseUrl,\n `/api/v1/voice/dialer/sessions/${sessionId}/resume`,\n apiKey,\n { method: \"POST\", body: { max_contacts: maxContacts } },\n );\n return resp.data ?? (resp as unknown as DialerSessionResumeResult);\n },\n\n /** Aggregated dialer analytics (daily breakdown or total). */\n async stats(params: DialerStatsParams = {}): Promise<DialerStatsResult> {\n const resp = await request<{ data?: DialerStatsResult }>(\n baseUrl,\n \"/api/v1/voice/dialer/stats\",\n apiKey,\n { query: params as Record<string, unknown> },\n );\n return resp.data ?? (resp as unknown as DialerStatsResult);\n },\n\n /** List dialer-eligible phone numbers with 7-day stats + daily limits. */\n async numbers(userEmail?: string): Promise<DialerNumbersListResult> {\n const resp = await request<{ data?: DialerNumbersListResult }>(\n baseUrl,\n \"/api/v1/voice/dialer/numbers\",\n apiKey,\n { query: userEmail ? { user_email: userEmail } : {} },\n );\n return resp.data ?? (resp as unknown as DialerNumbersListResult);\n },\n\n /** List missed inbound callbacks with caller / contact info. */\n async missedCallbacks(limit = 50): Promise<MissedCallbacksResult> {\n const resp = await request<{ data?: MissedCallbacksResult }>(\n baseUrl,\n \"/api/v1/voice/dialer/missed-callbacks\",\n apiKey,\n { query: { limit } },\n );\n return resp.data ?? (resp as unknown as MissedCallbacksResult);\n },\n\n /** AI grading for a single dialer call (returns \"pending\" while in progress). */\n async callGrading(roomName: string): Promise<CallGradingResult> {\n const resp = await request<{ data?: CallGradingResult }>(\n baseUrl,\n `/api/v1/voice/dialer/calls/${encodeURIComponent(roomName)}/grading`,\n apiKey,\n );\n return resp.data ?? (resp as unknown as CallGradingResult);\n },\n\n /** List voice agents available for dialer sessions (capped at 100; no pagination). */\n async agents(params: DialerAgentsListParams = {}): Promise<DialerAgentsListResult> {\n const resp = await request<{ data?: DialerAgentsListResult }>(\n baseUrl,\n \"/api/v1/voice/dialer/agents\",\n apiKey,\n { query: params as Record<string, unknown> },\n );\n return resp.data ?? (resp as unknown as DialerAgentsListResult);\n },\n\n /** Fetch the full transcript for a single dialer call. */\n async callTranscript(roomName: string): Promise<{ data: { status: string; transcript: Array<{ speaker: string; text: string; timestamp: number }> } }> {\n return request(\n baseUrl,\n `/api/v1/voice/dialer/calls/${encodeURIComponent(roomName)}/transcript`,\n apiKey,\n );\n },\n\n /** List dialer calls — pass `contact_id` or `user_email` to scope. */\n async listCalls(params: { contact_id?: number; user_email?: string; campaign_id?: string; date_from?: string; date_to?: string; limit?: number; page?: number } = {}): Promise<{ data: Array<Record<string, unknown>>; pagination?: VoicePagination }> {\n return request(\n baseUrl,\n \"/api/v1/voice/dialer/calls\",\n apiKey,\n { query: params as Record<string, unknown> },\n );\n },\n\n /** Convenience: list calls for a single contact. */\n async listCallsForContact(contactId: number, extra: { limit?: number } = {}): Promise<{ data: Array<Record<string, unknown>> }> {\n return request(\n baseUrl,\n \"/api/v1/voice/dialer/calls\",\n apiKey,\n { query: { contact_id: contactId, ...extra } },\n );\n },\n\n /** Convenience: list calls placed by a specific SDR. */\n async listCallsForSdr(userEmail: string, extra: { limit?: number; date_from?: string; date_to?: string } = {}): Promise<{ data: Array<Record<string, unknown>> }> {\n return request(\n baseUrl,\n \"/api/v1/voice/dialer/calls\",\n apiKey,\n { query: { user_email: userEmail, ...extra } },\n );\n },\n };\n\n return {\n /**\n * Start an AI voice session.\n * @deprecated Preview surface — for parallel-dialer flows use `voice.dialer.createSession()`.\n */\n async start(config: { agent?: string; contactId?: number; context?: Record<string, unknown> }): Promise<VoiceSession> {\n const resp = await request<{ data?: VoiceSession }>(\n baseUrl,\n \"/api/v1/voice/sessions\",\n apiKey,\n { method: \"POST\", body: config },\n );\n return resp.data ?? (resp as unknown as VoiceSession);\n },\n\n /**\n * Get call analysis for a completed session.\n * @deprecated Preview surface — for dialer-call grading use `voice.dialer.callGrading(roomName)`.\n */\n async analysis(sessionId: string): Promise<CallAnalysis> {\n const resp = await request<{ data?: CallAnalysis }>(\n baseUrl,\n `/api/v1/voice/sessions/${sessionId}/analysis`,\n apiKey,\n );\n return resp.data ?? (resp as unknown as CallAnalysis);\n },\n\n /** Listen for voice events. */\n on(event: VoiceEvent, callback: VoiceCallback): void {\n if (!listeners.has(event)) listeners.set(event, []);\n listeners.get(event)!.push(callback);\n },\n\n /** Parallel-dialer session control + analytics. */\n dialer,\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface LandingPage {\n id: string;\n title: string;\n slug: string;\n status: string;\n published_url: string | null;\n}\n\n/**\n * Landing pages - clone, create, publish. Requires API key (server-side). On the\n * hardened HTTP core: throws a typed `G8Error` on failure and retries transient\n * errors.\n */\nexport const createPagesClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** Clone a landing page from any URL. */\n async clone(url: string): Promise<LandingPage> {\n const resp = await request<{ data?: LandingPage }>(baseUrl, \"/api/v1/landing-pages/clone-url\", apiKey, {\n method: \"POST\",\n body: { url },\n });\n return resp.data ?? (resp as unknown as LandingPage);\n },\n\n /** Create a landing page from a template. */\n async create(config: { template?: string; title?: string; content?: Record<string, unknown> }): Promise<LandingPage> {\n const resp = await request<{ data?: LandingPage }>(baseUrl, \"/api/v1/landing-pages\", apiKey, {\n method: \"POST\",\n body: config,\n });\n return resp.data ?? (resp as unknown as LandingPage);\n },\n\n /** Publish a landing page to CDN. */\n async publish(pageId: string): Promise<{ url: string }> {\n const data = await request<{ published_url?: string; data?: { published_url?: string } }>(\n baseUrl,\n `/api/v1/landing-pages/${pageId}/publish`,\n apiKey,\n { method: \"POST\" },\n );\n return { url: data.published_url || data.data?.published_url || \"\" };\n },\n };\n};\n","import { createHmac, timingSafeEqual } from \"node:crypto\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\n/**\n * Known graph8 webhook event types.\n *\n * Source of truth is the backend ``WEBHOOK_EVENTS`` catalog\n * (campaign_builder/services/webhook_service.py). Keep in sync when the backend\n * adds events. ``WebhookEvent`` also accepts any string so a newly-added\n * backend event never breaks a client that hasn't upgraded.\n */\nexport const KNOWN_WEBHOOK_EVENTS = [\n \"campaign.created\",\n \"campaign.updated\",\n \"campaign.deleted\",\n \"campaign.launched\",\n \"campaign.paused\",\n \"campaign.completed\",\n \"campaign.status_changed\",\n \"campaign.content_ready\",\n \"document.generated\",\n \"document.failed\",\n \"intelligence.completed\",\n \"intelligence.failed\",\n \"company.enriched\",\n \"company_intelligence.completed\",\n \"audience.ready\",\n \"audience.failed\",\n \"sequence.deployed\",\n \"sequence.started\",\n \"sequence.paused\",\n \"sequence.completed\",\n \"engagement.email_sent\",\n \"engagement.email_replied\",\n \"engagement.email_bounced\",\n \"engagement.email_skipped\",\n \"engagement.call_dispatched\",\n \"engagement.sms_sent\",\n \"engagement.sms_replied\",\n \"engagement.whatsapp_sent\",\n \"engagement.linkedin_connection_sent\",\n \"engagement.linkedin_message_sent\",\n \"engagement.linkedin_inmail_sent\",\n \"engagement.linkedin_reply_received\",\n \"engagement.linkedin_connection_accepted\",\n \"meeting.booked\",\n \"meeting.cancelled\",\n \"meeting.rescheduled\",\n] as const;\n\n// Union of known events for autocomplete, plus `string` so unknown/new backend\n// events still type-check (Stripe-style forward compatibility).\nexport type WebhookEvent = (typeof KNOWN_WEBHOOK_EVENTS)[number] | (string & {});\n\n/** The decoded body graph8 delivers to a webhook endpoint. */\nexport interface WebhookEventPayload {\n event: WebhookEvent;\n timestamp: string;\n data: Record<string, unknown>;\n org_id: string;\n /** Stable per-delivery id (present once the backend adds it; for consumer dedup). */\n id?: string;\n}\n\nexport interface ConstructEventOptions {\n /**\n * Reject events whose ``X-Studio-Timestamp`` is older (or newer) than this\n * many seconds — replay protection. Disabled when 0/undefined.\n */\n toleranceSeconds?: number;\n}\n\n/** Thrown by {@link constructEvent} when a webhook cannot be verified. */\nexport class WebhookSignatureError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"WebhookSignatureError\";\n }\n}\n\nfunction timingSafeEqualHex(a: string, b: string): boolean {\n // Length check first: timingSafeEqual throws on length mismatch.\n if (a.length !== b.length) return false;\n try {\n const enc = new TextEncoder();\n return timingSafeEqual(enc.encode(a), enc.encode(b));\n } catch {\n return false;\n }\n}\n\n/**\n * Verify the HMAC-SHA256 signature of an incoming graph8 webhook and return the\n * parsed event. Server-side only (needs the per-endpoint signing secret).\n *\n * Mirrors the backend signing scheme exactly: the signature is\n * ``HMAC_SHA256(secret, `${timestamp}.${rawBody}`)`` hex-encoded, delivered in\n * the ``X-Studio-Signature`` header alongside the unix ``X-Studio-Timestamp``.\n *\n * @param payload The RAW request body string (verify before JSON.parse — re-serializing changes bytes).\n * @param signature The ``X-Studio-Signature`` header (an optional ``sha256=`` prefix is tolerated).\n * @param timestamp The ``X-Studio-Timestamp`` header (unix seconds).\n * @param secret The endpoint's signing secret.\n * @throws {WebhookSignatureError} on a missing/invalid signature, stale timestamp, or bad JSON.\n *\n * @example\n * app.post(\"/webhooks/graph8\", (req, res) => {\n * const event = g8.webhooks.constructEvent(\n * req.rawBody,\n * req.header(\"X-Studio-Signature\"),\n * req.header(\"X-Studio-Timestamp\"),\n * process.env.G8_WEBHOOK_SECRET,\n * { toleranceSeconds: 300 },\n * );\n * if (event.event === \"meeting.booked\") { ... }\n * res.sendStatus(200);\n * });\n */\nexport function constructEvent(\n payload: string,\n signature: string,\n timestamp: string | number,\n secret: string,\n opts: ConstructEventOptions = {},\n): WebhookEventPayload {\n if (!signature) throw new WebhookSignatureError(\"Missing X-Studio-Signature header\");\n if (timestamp === undefined || timestamp === null || timestamp === \"\") {\n throw new WebhookSignatureError(\"Missing X-Studio-Timestamp header\");\n }\n if (!secret) throw new WebhookSignatureError(\"Missing signing secret\");\n\n const ts = typeof timestamp === \"number\" ? timestamp : parseInt(timestamp, 10);\n if (!Number.isFinite(ts)) throw new WebhookSignatureError(\"Invalid X-Studio-Timestamp header\");\n\n const tolerance = opts.toleranceSeconds ?? 0;\n if (tolerance > 0) {\n const ageSeconds = Math.floor(Date.now() / 1000) - ts;\n if (Math.abs(ageSeconds) > tolerance) {\n throw new WebhookSignatureError(`Timestamp outside tolerance (${ageSeconds}s > ${tolerance}s)`);\n }\n }\n\n const expected = createHmac(\"sha256\", secret).update(`${ts}.${payload}`).digest(\"hex\");\n const provided = signature.startsWith(\"sha256=\") ? signature.slice(7) : signature;\n if (!timingSafeEqualHex(expected, provided)) {\n throw new WebhookSignatureError(\"Signature verification failed\");\n }\n\n try {\n return JSON.parse(payload) as WebhookEventPayload;\n } catch {\n throw new WebhookSignatureError(\"Invalid JSON payload\");\n }\n}\n\n/**\n * Webhooks client (server-side). graph8 webhooks are PUSH — graph8 POSTs to your\n * endpoint; you verify each delivery with {@link constructEvent}. (The previous\n * polling implementation hit a feed endpoint that never existed and is removed.)\n */\nexport const createWebhooksClient = (_apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n return {\n /** Base URL the webhook subscription API lives under. */\n baseUrl,\n /** Known event types (for autocomplete / validation). */\n knownEvents: KNOWN_WEBHOOK_EVENTS,\n /** Verify an incoming webhook's HMAC signature and return the parsed event. */\n constructEvent(\n payload: string,\n signature: string,\n timestamp: string | number,\n secret: string,\n opts?: ConstructEventOptions,\n ): WebhookEventPayload {\n return constructEvent(payload, signature, timestamp, secret, opts);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface Contact {\n id: number;\n first_name: string | null;\n last_name: string | null;\n work_email: string | null;\n job_title: string | null;\n seniority_level: string | null;\n company_name: string | null;\n company_domain: string | null;\n linkedin_url: string | null;\n direct_phone: string | null;\n mobile_phone: string | null;\n city: string | null;\n state: string | null;\n country: string | null;\n}\n\nexport interface ContactListParams {\n page?: number;\n limit?: number;\n email?: string;\n name?: string;\n job_title?: string;\n seniority_level?: string;\n company_name?: string;\n country?: string;\n list_id?: number;\n}\n\nexport interface ContactCreateParams {\n work_email: string;\n first_name?: string;\n last_name?: string;\n job_title?: string;\n company_domain?: string;\n linkedin_url?: string;\n direct_phone?: string;\n mobile_phone?: string;\n city?: string;\n state?: string;\n country?: string;\n list_id?: number;\n}\n\nexport interface ContactUpdateParams {\n first_name?: string;\n last_name?: string;\n work_email?: string;\n job_title?: string;\n company_domain?: string;\n linkedin_url?: string;\n direct_phone?: string;\n mobile_phone?: string;\n city?: string;\n state?: string;\n country?: string;\n}\n\n/** A column definition on contacts (base or custom). */\nexport interface ContactColumn {\n id: number | null;\n title: string;\n data_type: string;\n name: string | null;\n /** Stringified list_id when list-scoped, otherwise null/empty for global. */\n object_id: string | null;\n is_global: boolean;\n}\n\nexport interface ContactColumnCreateParams {\n title: string;\n /** Email of the user creating the column. Required by the backend (audit). */\n created_by: string;\n /** \"text\" (default) — additional types may be added later. */\n data_type?: string;\n /** If set, the column is list-specific. Omit for org-wide global column. */\n list_id?: number;\n}\n\n/**\n * Contacts API - full CRUD for CRM contacts. Requires API key (server-side).\n */\nexport const createContactsClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** List contacts with optional filters. */\n async list(params: ContactListParams = {}): Promise<{ data: Contact[]; total: number }> {\n return request(baseUrl, \"/api/v1/contacts\", apiKey, {\n query: params as Record<string, unknown>,\n });\n },\n\n /** Get a single contact by ID. */\n async get(contactId: number): Promise<Contact> {\n const resp = await request<{ data?: Contact }>(baseUrl, `/api/v1/contacts/${contactId}`, apiKey);\n return resp.data ?? (resp as unknown as Contact);\n },\n\n /**\n * Create a new contact. Pass `idempotencyKey` to make a retry safe — the\n * same key returns the first result instead of creating a duplicate (A6).\n */\n async create(contact: ContactCreateParams, idempotencyKey?: string): Promise<Contact> {\n const resp = await request<{ data?: Contact }>(baseUrl, \"/api/v1/contacts\", apiKey, {\n method: \"POST\",\n body: contact,\n idempotencyKey,\n });\n return resp.data ?? (resp as unknown as Contact);\n },\n\n /** Update a contact (partial). */\n async update(contactId: number, fields: ContactUpdateParams): Promise<{ updated: number }> {\n return request(baseUrl, `/api/v1/contacts/${contactId}`, apiKey, {\n method: \"PATCH\",\n body: fields,\n });\n },\n\n /** Delete a contact (soft-delete). */\n async delete(contactId: number): Promise<{ deleted: boolean }> {\n return request(baseUrl, `/api/v1/contacts/${contactId}`, apiKey, { method: \"DELETE\" });\n },\n\n /** List custom contact columns. Pass listId to include list-specific columns. */\n async listColumns(listId?: number): Promise<{ data: ContactColumn[] }> {\n return request(baseUrl, \"/api/v1/contacts/columns\", apiKey, {\n query: listId != null ? { list_id: listId } : undefined,\n });\n },\n\n /** Create a custom contact column. Global if list_id is omitted, list-scoped otherwise. */\n async createColumn(params: ContactColumnCreateParams): Promise<ContactColumn> {\n const resp = await request<{ data?: ContactColumn }>(baseUrl, \"/api/v1/contacts/columns/create\", apiKey, {\n method: \"POST\",\n body: {\n title: params.title,\n data_type: params.data_type || \"text\",\n list_id: params.list_id ?? null,\n created_by: params.created_by,\n },\n });\n return resp.data ?? (resp as unknown as ContactColumn);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface Company {\n id: number;\n name: string | null;\n domain: string | null;\n industry: string | null;\n employee_count: number | null;\n revenue: number | null;\n founded_year: number | null;\n description: string | null;\n linkedin_url: string | null;\n country: string | null;\n state: string | null;\n city: string | null;\n}\n\nexport interface CompanyListParams {\n page?: number;\n limit?: number;\n domain?: string;\n industry?: string;\n name?: string;\n country?: string;\n}\n\nexport interface CompanyUpdateParams {\n name?: string;\n domain?: string;\n industry?: string;\n description?: string;\n linkedin_url?: string;\n country?: string;\n state?: string;\n city?: string;\n}\n\nexport interface CompanyContact {\n id: number;\n first_name: string | null;\n last_name: string | null;\n work_email: string | null;\n job_title: string | null;\n}\n\n/** A column definition on companies (base or custom). */\nexport interface CompanyColumn {\n id: number | null;\n title: string;\n data_type: string;\n name: string | null;\n /** Stringified list_id when list-scoped, otherwise null/empty for global. */\n object_id: string | null;\n is_global: boolean;\n}\n\nexport interface CompanyColumnCreateParams {\n title: string;\n /** Email of the user creating the column. Required by the backend (audit). */\n created_by: string;\n /** \"text\" (default) — additional types may be added later. */\n data_type?: string;\n /** If set, the column is list-specific. Omit for org-wide global column. */\n list_id?: number;\n}\n\n/**\n * Companies API - search and manage CRM companies. Requires API key (server-side).\n */\nexport const createCompaniesClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** List companies with optional filters. */\n async list(params: CompanyListParams = {}): Promise<{ data: Company[]; total: number }> {\n return request(baseUrl, \"/api/v1/companies\", apiKey, { query: params as Record<string, unknown> });\n },\n\n /** Get a single company by ID. */\n async get(companyId: number): Promise<Company> {\n const resp = await request<{ data?: Company }>(baseUrl, `/api/v1/companies/${companyId}`, apiKey);\n return resp.data ?? (resp as unknown as Company);\n },\n\n /** Get contacts belonging to a company. */\n async contacts(companyId: number, limit = 50, offset = 0): Promise<{ data: CompanyContact[]; total: number }> {\n return request(baseUrl, `/api/v1/companies/${companyId}/contacts`, apiKey, { query: { limit, offset } });\n },\n\n /** Update a company (partial). */\n async update(companyId: number, fields: CompanyUpdateParams): Promise<{ updated: number }> {\n return request(baseUrl, `/api/v1/companies/${companyId}`, apiKey, { method: \"PATCH\", body: fields });\n },\n\n /** Delete a company (soft-delete). */\n async delete(companyId: number): Promise<{ deleted: boolean }> {\n return request(baseUrl, `/api/v1/companies/${companyId}`, apiKey, { method: \"DELETE\" });\n },\n\n /** List custom company columns. Pass listId to include list-specific columns. */\n async listColumns(listId?: number): Promise<{ data: CompanyColumn[] }> {\n return request(baseUrl, \"/api/v1/companies/columns\", apiKey, {\n query: listId != null ? { list_id: listId } : undefined,\n });\n },\n\n /** Create a custom company column. Global if list_id is omitted, list-scoped otherwise. */\n async createColumn(params: CompanyColumnCreateParams): Promise<CompanyColumn> {\n const resp = await request<{ data?: CompanyColumn }>(baseUrl, \"/api/v1/companies/columns/create\", apiKey, {\n method: \"POST\",\n body: {\n title: params.title,\n data_type: params.data_type || \"text\",\n list_id: params.list_id ?? null,\n created_by: params.created_by,\n },\n });\n return resp.data ?? (resp as unknown as CompanyColumn);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface ContactList {\n id: number;\n title: string;\n type: \"contacts\" | \"companies\";\n contact_count: number | null;\n created_at: string | null;\n}\n\nexport interface ListContact {\n id: number;\n first_name: string | null;\n last_name: string | null;\n work_email: string | null;\n job_title: string | null;\n company_name: string | null;\n}\n\n/**\n * Lists API - manage contact and company lists. Requires API key (server-side).\n */\nexport const createListsClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** List all lists. */\n async list(page = 1, limit = 50): Promise<{ data: ContactList[]; total: number }> {\n return request(baseUrl, \"/api/v1/lists\", apiKey, { query: { page, limit } });\n },\n\n /** Create a new list. */\n async create(title: string, type: \"contacts\" | \"companies\" = \"contacts\"): Promise<ContactList> {\n const resp = await request<{ data?: ContactList }>(baseUrl, \"/api/v1/lists\", apiKey, {\n method: \"POST\",\n body: { title, type },\n });\n return resp.data ?? (resp as unknown as ContactList);\n },\n\n /** Delete a list (soft-delete). */\n async delete(listId: number): Promise<{ deleted: boolean }> {\n return request(baseUrl, `/api/v1/lists/${listId}`, apiKey, { method: \"DELETE\" });\n },\n\n /** Get contacts in a list. */\n async contacts(listId: number, page = 1, limit = 50): Promise<{ data: ListContact[]; total: number }> {\n return request(baseUrl, `/api/v1/lists/${listId}/contacts`, apiKey, { query: { page, limit } });\n },\n\n /** Add contacts to a list. */\n async addContacts(listId: number, contactIds: number[]): Promise<{ added: number }> {\n return request(baseUrl, `/api/v1/lists/${listId}/contacts`, apiKey, {\n method: \"POST\",\n body: { contact_ids: contactIds },\n });\n },\n\n /** Remove contacts from a list. */\n async removeContacts(listId: number, contactIds: number[]): Promise<{ removed: number }> {\n return request(baseUrl, `/api/v1/lists/${listId}/contacts`, apiKey, {\n method: \"DELETE\",\n body: { contact_ids: contactIds },\n });\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface Note {\n id: string;\n entity_type: string;\n entity_id: string;\n content: string;\n created_by: string | null;\n created_by_name: string | null;\n created_at: string | null;\n updated_at: string | null;\n}\n\n/**\n * Notes API - CRUD for notes attached to contacts. Requires API key (server-side).\n *\n * Backed by:\n * GET /api/v1/contacts/{contact_id}/notes\n * POST /api/v1/contacts/{contact_id}/notes\n * PATCH /api/v1/notes/{note_id}\n * DELETE /api/v1/notes/{note_id}\n */\nexport const createNotesClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** List all notes on a contact. */\n async list(contactId: number): Promise<{ data: Note[] }> {\n return request(baseUrl, `/api/v1/contacts/${contactId}/notes`, apiKey);\n },\n\n /** Create a note on a contact. */\n async create(contactId: number, content: string): Promise<Note> {\n const resp = await request<{ data?: Note }>(baseUrl, `/api/v1/contacts/${contactId}/notes`, apiKey, {\n method: \"POST\",\n body: { content },\n });\n return resp.data ?? (resp as unknown as Note);\n },\n\n /** Update a note's content. */\n async update(noteId: string, content: string): Promise<Note> {\n const resp = await request<{ data?: Note }>(baseUrl, `/api/v1/notes/${noteId}`, apiKey, {\n method: \"PATCH\",\n body: { content },\n });\n return resp.data ?? (resp as unknown as Note);\n },\n\n /** Delete a note. */\n async delete(noteId: string): Promise<{ data: { deleted: boolean } }> {\n return request(baseUrl, `/api/v1/notes/${noteId}`, apiKey, { method: \"DELETE\" });\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface Task {\n id: string;\n entity_type: string | null;\n entity_id: string | null;\n title: string;\n description: string | null;\n due_date: string | null;\n assignee_id: string | null;\n assignee_name: string | null;\n /** \"open\" | \"completed\" (other values may appear if the backend adds states later) */\n status: string | null;\n /** 0=none, 1=urgent, 2=high, 3=normal, 4=low */\n priority: number | null;\n task_type: string | null;\n created_by: string | null;\n created_at: string | null;\n updated_at: string | null;\n /** Parent task UUID when this row is a subtask, else null. One level deep. */\n parent_task_id?: string | null;\n /** Sort position within the parent's subtasks. 0 when not a subtask. */\n subtask_sort_order?: number | null;\n /** Number of subtasks under this task (top-level rows only). */\n subtask_count?: number | null;\n /** Subset of subtask_count whose status is \"completed\". */\n completed_subtask_count?: number | null;\n}\n\nexport interface TaskCreateParams {\n title: string;\n description?: string;\n /** ISO 8601 date string. */\n due_date?: string;\n assignee_id?: string;\n /** 0=none, 1=urgent, 2=high, 3=normal, 4=low */\n priority?: number;\n /**\n * When set, the new task is created as a subtask of this parent. Parent\n * must exist and must not itself be a subtask (subtasks are one level\n * deep).\n */\n parent_task_id?: string;\n /**\n * Sort position within the parent's subtasks. Omit to append at the end.\n */\n subtask_sort_order?: number;\n}\n\nexport interface TaskUpdateParams {\n title?: string;\n description?: string;\n due_date?: string;\n assignee_id?: string;\n /** \"open\" | \"completed\" */\n status?: string;\n priority?: number;\n /**\n * Re-parent this task into a subtask of the given parent. Parent must\n * exist, must not itself be a subtask, and a task that already has\n * subtasks of its own cannot be demoted into a subtask.\n */\n parent_task_id?: string;\n /** Reorder within the parent's subtasks. Can be sent alone. */\n subtask_sort_order?: number;\n}\n\nexport interface TaskListParams {\n /** \"open\" | \"completed\" */\n status?: string;\n /** 0-4 */\n priority?: number;\n assignee_id?: string;\n /** Substring search on title. */\n search?: string;\n}\n\n/**\n * Tasks API - CRUD for tasks attached to contacts. Requires API key (server-side).\n *\n * Backed by:\n * GET /api/v1/contacts/{contact_id}/tasks\n * GET /api/v1/tasks\n * POST /api/v1/contacts/{contact_id}/tasks\n * PATCH /api/v1/tasks/{task_id}\n * DELETE /api/v1/tasks/{task_id}\n */\nexport const createTasksClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** List tasks on a single contact. Optional status filter (\"open\" | \"completed\"). */\n async listForContact(contactId: number, status?: string): Promise<{ data: Task[] }> {\n return request(baseUrl, `/api/v1/contacts/${contactId}/tasks`, apiKey, {\n query: status ? { status } : undefined,\n });\n },\n\n /** List all tasks org-wide with optional filters. */\n async list(params: TaskListParams = {}): Promise<{ data: Task[] }> {\n return request(baseUrl, \"/api/v1/tasks\", apiKey, { query: params as Record<string, unknown> });\n },\n\n /** Create a task on a contact. */\n async create(contactId: number, task: TaskCreateParams): Promise<Task> {\n const resp = await request<{ data?: Task }>(baseUrl, `/api/v1/contacts/${contactId}/tasks`, apiKey, {\n method: \"POST\",\n body: task,\n });\n return resp.data ?? (resp as unknown as Task);\n },\n\n /** Update a task (partial). */\n async update(taskId: string, fields: TaskUpdateParams): Promise<Task> {\n const resp = await request<{ data?: Task }>(baseUrl, `/api/v1/tasks/${taskId}`, apiKey, {\n method: \"PATCH\",\n body: fields,\n });\n return resp.data ?? (resp as unknown as Task);\n },\n\n /** Delete a task. */\n async delete(taskId: string): Promise<{ data: { deleted: boolean } }> {\n return request(baseUrl, `/api/v1/tasks/${taskId}`, apiKey, { method: \"DELETE\" });\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\n/** A field (column) definition on contacts or companies — base or custom. */\nexport interface Field {\n id: number | null;\n title: string;\n /** Internal column name (slug). */\n name: string | null;\n /** Currently only \"text\" is supported; other types may be added later. */\n data_type: string;\n /** True if available org-wide, false if list-specific. */\n is_global: boolean;\n}\n\n/** Created custom field (column). */\nexport interface CreatedField {\n id: number;\n title: string;\n data_type: string;\n name: string;\n list_id: number | null;\n is_global: boolean;\n}\n\nexport interface FieldCreateParams {\n title: string;\n /** \"contacts\" or \"companies\". Defaults to \"contacts\" on the backend. */\n entity?: \"contacts\" | \"companies\";\n /** \"text\" (default) — additional types may be added later. */\n data_type?: string;\n /** If set, the field is list-specific. Omit for org-wide global field. */\n list_id?: number;\n}\n\nexport interface FieldDeleteParams {\n entity?: \"contacts\" | \"companies\";\n /**\n * Optional list scope guard. If provided, the column must belong to this\n * list or the request returns 404. Use this to prevent accidentally\n * deleting a column on a different list in the same org.\n */\n list_id?: number;\n}\n\nexport interface SetFieldValueParams {\n /** Contact ID (entity='contacts') or company ID (entity='companies'). */\n record_id: number;\n /** Value to write. Pass null/undefined to clear the field. */\n value?: string | null;\n entity?: \"contacts\" | \"companies\";\n}\n\n/**\n * Fields API - manage custom fields (columns) on contacts and companies.\n * Requires API key (server-side). On the hardened HTTP core: throws a typed\n * `G8Error` on failure and retries transient errors.\n *\n * Backed by:\n * GET /api/v1/fields — list contact fields\n * GET /api/v1/fields/companies — list company fields\n * POST /api/v1/fields — create a custom field\n * DELETE /api/v1/fields/{column_id} — delete a custom field\n * PATCH /api/v1/fields/{column_id}/values — set value on a single record\n */\nexport const createFieldsClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** List contact fields (base + custom). Pass listId to include list-specific custom fields. */\n async listContactFields(listId?: number): Promise<{ data: Field[] }> {\n return request(baseUrl, \"/api/v1/fields\", apiKey, { query: listId != null ? { list_id: listId } : undefined });\n },\n\n /** List company fields (base + custom). Pass listId to include list-specific custom fields. */\n async listCompanyFields(listId?: number): Promise<{ data: Field[] }> {\n return request(baseUrl, \"/api/v1/fields/companies\", apiKey, {\n query: listId != null ? { list_id: listId } : undefined,\n });\n },\n\n /** Create a custom field on contacts (default) or companies. */\n async create(params: FieldCreateParams): Promise<CreatedField> {\n const resp = await request<{ data?: CreatedField }>(baseUrl, \"/api/v1/fields\", apiKey, {\n method: \"POST\",\n body: {\n title: params.title,\n data_type: params.data_type || \"text\",\n list_id: params.list_id ?? null,\n entity: params.entity || \"contacts\",\n },\n });\n return resp.data ?? (resp as unknown as CreatedField);\n },\n\n /** Delete a custom field (soft-delete). Pass list_id to scope-guard against cross-list deletion. */\n async delete(\n columnId: number,\n params: FieldDeleteParams = {},\n ): Promise<{ data: { column_id: number; deleted: boolean } }> {\n const query: Record<string, unknown> = { entity: params.entity || \"contacts\" };\n if (params.list_id != null) query.list_id = params.list_id;\n return request(baseUrl, `/api/v1/fields/${columnId}`, apiKey, { method: \"DELETE\", query });\n },\n\n /** Set a custom field value on a single contact or company row. Pass value=null to clear. */\n async setValue(\n columnId: number,\n params: SetFieldValueParams,\n ): Promise<{ data: { column_id: number; record_id: number; updated: boolean } }> {\n return request(baseUrl, `/api/v1/fields/${columnId}/values`, apiKey, {\n method: \"PATCH\",\n body: { record_id: params.record_id, value: params.value ?? null, entity: params.entity || \"contacts\" },\n });\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface Deal {\n id: string | null;\n name: string | null;\n description: string | null;\n amount: number | null;\n currency: string | null;\n stage_id: string | null;\n stage_name: string | null;\n pipeline_id: string | null;\n /** Linked company ID (mashup_company_id), if any. */\n company_id: number | string | null;\n owner_id: string | null;\n /** ISO 8601 date. */\n close_date: string | null;\n created_at: string | null;\n updated_at: string | null;\n}\n\nexport interface DealCreateParams {\n name: string;\n /** Linked company ID. */\n company_id?: number;\n description?: string;\n amount?: number;\n /** Default: \"USD\". */\n currency?: string;\n /** Stage ID from the org's pipelines. Defaults to first stage of default pipeline if omitted. */\n stage_id?: string;\n /** Pipeline ID. Defaults to org's default pipeline if omitted. */\n pipeline_id?: string;\n /** ISO 8601 close date. */\n close_date?: string;\n}\n\nexport interface DealUpdateParams {\n name?: string;\n description?: string;\n amount?: number;\n currency?: string;\n stage_id?: string;\n /** ISO 8601 close date. */\n close_date?: string;\n}\n\nexport interface DealListParams {\n page?: number;\n limit?: number;\n stage_id?: string;\n pipeline_id?: string;\n /** Substring search on deal name. */\n search?: string;\n}\n\nexport interface PipelineStage {\n id: string;\n name: string;\n probability: number | null;\n position: number | null;\n stage_type: string | null;\n color: string | null;\n required_elements: string[];\n recommended_elements: string[];\n channel_scripts: Record<string, string>;\n}\n\nexport interface Pipeline {\n id: string;\n name: string;\n is_default: boolean;\n stages: PipelineStage[];\n}\n\n/** Trimmed deal shape returned by /contacts/{id}/deals and /companies/{id}/deals. */\nexport interface ContactDeal {\n deal_id: string | null;\n name: string | null;\n stage: string | null;\n value: number | null;\n currency: string | null;\n role: string | null;\n pipeline_id: string | null;\n close_date: string | null;\n owner_id: string | null;\n created_at: string | null;\n}\n\nexport interface PaginationMeta {\n page: number;\n limit: number;\n total: number;\n has_next: boolean;\n}\n\n/**\n * Deals API - CRUD for deals + pipelines. Requires API key (server-side).\n *\n * Backed by:\n * GET /api/v1/deals/pipelines\n * GET /api/v1/deals\n * POST /api/v1/deals\n * GET /api/v1/deals/{deal_id}\n * PATCH /api/v1/deals/{deal_id}\n * DELETE /api/v1/deals/{deal_id}\n * GET /api/v1/contacts/{contact_id}/deals\n * GET /api/v1/companies/{company_id}/deals\n */\nexport const createDealsClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** List all deal pipelines and their stages. */\n async pipelines(): Promise<{ data: Pipeline[] }> {\n return request(baseUrl, \"/api/v1/deals/pipelines\", apiKey);\n },\n\n /** List deals org-wide with optional filters and pagination. */\n async list(params: DealListParams = {}): Promise<{ data: Deal[]; pagination?: PaginationMeta }> {\n return request(baseUrl, \"/api/v1/deals\", apiKey, { query: params as Record<string, unknown> });\n },\n\n /** Create a new deal. */\n async create(deal: DealCreateParams): Promise<Deal> {\n const resp = await request<{ data?: Deal }>(baseUrl, \"/api/v1/deals\", apiKey, { method: \"POST\", body: deal });\n return resp.data ?? (resp as unknown as Deal);\n },\n\n /** Get a single deal by ID. */\n async get(dealId: string): Promise<Deal> {\n const resp = await request<{ data?: Deal }>(baseUrl, `/api/v1/deals/${dealId}`, apiKey);\n return resp.data ?? (resp as unknown as Deal);\n },\n\n /** Update a deal (partial). */\n async update(dealId: string, fields: DealUpdateParams): Promise<Deal> {\n const resp = await request<{ data?: Deal }>(baseUrl, `/api/v1/deals/${dealId}`, apiKey, {\n method: \"PATCH\",\n body: fields,\n });\n return resp.data ?? (resp as unknown as Deal);\n },\n\n /** Delete a deal. */\n async delete(dealId: string): Promise<{ data: { deleted: boolean } }> {\n return request(baseUrl, `/api/v1/deals/${dealId}`, apiKey, { method: \"DELETE\" });\n },\n\n /** Get all deals associated with a contact. */\n async forContact(contactId: number): Promise<{ data: ContactDeal[] }> {\n return request(baseUrl, `/api/v1/contacts/${contactId}/deals`, apiKey);\n },\n\n /** Get all deals associated with a company. */\n async forCompany(companyId: number): Promise<{ data: ContactDeal[] }> {\n return request(baseUrl, `/api/v1/companies/${companyId}/deals`, apiKey);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\n/**\n * Inbox channel — `email`, `sms`, or `linkedin` (HeyReach internally).\n * Defaults to `email` on routes that accept this as a query param.\n */\nexport type InboxChannel = \"email\" | \"sms\" | \"linkedin\";\n\nexport interface InboxContact {\n name?: string | null;\n email?: string | null;\n company?: string | null;\n [key: string]: unknown;\n}\n\nexport interface InboxTag {\n id: string;\n name: string;\n}\n\nexport interface InboxAssignee {\n email: string;\n name?: string | null;\n [key: string]: unknown;\n}\n\nexport interface InboxMessage {\n message_id: string | null;\n from_address: string | null;\n to_addresses: string[];\n content: string | null;\n /** \"USER\", \"AI\", or \"OTHER\". */\n responder: string | null;\n date: string | null;\n is_draft: boolean;\n}\n\nexport interface InboxThread {\n id: string;\n /** \"email\", \"sms\", or \"linkedin\". */\n channel: string;\n subject: string | null;\n contact: InboxContact | null;\n messages: InboxMessage[];\n /** \"open\", \"responded\", \"ai_responded\", etc. */\n status: string | null;\n tags: InboxTag[];\n assignees: InboxAssignee[];\n created_at: string | null;\n updated_at: string | null;\n}\n\nexport interface InboxListParams {\n channel?: InboxChannel;\n sequence_id?: string;\n /** Filter by thread status (e.g. \"open\", \"responded\", \"ai_responded\"). */\n status?: string;\n /** Filter by assignee email. */\n assignee?: string;\n /** Filter by tag ID. */\n tag?: string;\n page?: number;\n /** Default 50, max 100. */\n page_size?: number;\n}\n\nexport interface InboxAssignResult {\n assigned: boolean;\n assignee: string;\n count: number;\n [key: string]: unknown;\n}\n\nexport interface InboxTagResult {\n tagged: boolean;\n tag_count: number;\n [key: string]: unknown;\n}\n\nexport interface InboxDraft {\n /** HTML body. */\n content: string;\n /** Plain-text alternative, if available. */\n plain_content: string | null;\n /** Credits charged for AI generation. */\n credits_charged: number;\n}\n\nexport interface InboxSendParams {\n body: string;\n channel: InboxChannel;\n subject?: string;\n /** Recipient override — email, phone, or LinkedIn ID. */\n to?: string;\n /** Sender override — mailbox email, Twilio number, or LinkedIn account ID. */\n from_address?: string;\n}\n\nexport interface InboxSendResult {\n message_id: string | null;\n status: string;\n channel: string;\n}\n\n/**\n * Inbox API — read + reply to multi-channel inbox threads (email, SMS, LinkedIn/HeyReach).\n * Requires API key (server-side). On the hardened HTTP core: throws a typed\n * `G8Error` on failure (e.g. 402 when an AI draft exceeds your credit balance)\n * and retries transient errors.\n *\n * Backed by:\n * GET /api/v1/inbox\n * GET /api/v1/inbox/{reply_id}\n * POST /api/v1/inbox/{reply_id}/assign\n * POST /api/v1/inbox/{reply_id}/tag\n * GET /api/v1/inbox/{reply_id}/draft (charges credits, 402 on insufficient balance)\n * POST /api/v1/inbox/{reply_id}/send\n */\nexport const createInboxClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** List inbox threads across email, SMS, and LinkedIn. */\n async list(params: InboxListParams = {}): Promise<{ data: InboxThread[] }> {\n return request(baseUrl, \"/api/v1/inbox\", apiKey, { query: params as Record<string, unknown> });\n },\n\n /** Get a single inbox thread. Defaults to email channel. */\n async get(replyId: string, channel: InboxChannel = \"email\"): Promise<InboxThread> {\n const resp = await request<{ data?: InboxThread }>(baseUrl, `/api/v1/inbox/${replyId}`, apiKey, {\n query: { channel },\n });\n return resp.data ?? (resp as unknown as InboxThread);\n },\n\n /** Assign a user to an inbox thread. */\n async assign(replyId: string, assigneeEmail: string, channel: InboxChannel = \"email\"): Promise<InboxAssignResult> {\n const resp = await request<{ data?: InboxAssignResult }>(baseUrl, `/api/v1/inbox/${replyId}/assign`, apiKey, {\n method: \"POST\",\n query: { channel },\n body: { assignee_email: assigneeEmail },\n });\n return resp.data ?? (resp as unknown as InboxAssignResult);\n },\n\n /** Attach tag IDs to an inbox thread. */\n async tag(replyId: string, tagIds: string[], channel: InboxChannel = \"email\"): Promise<InboxTagResult> {\n const resp = await request<{ data?: InboxTagResult }>(baseUrl, `/api/v1/inbox/${replyId}/tag`, apiKey, {\n method: \"POST\",\n query: { channel },\n body: { tag_ids: tagIds },\n });\n return resp.data ?? (resp as unknown as InboxTagResult);\n },\n\n /**\n * Generate an AI draft reply for a thread.\n * Charges credits — server returns 402 if balance is insufficient.\n */\n async draft(replyId: string, channel: InboxChannel = \"email\"): Promise<InboxDraft> {\n const resp = await request<{ data?: InboxDraft }>(baseUrl, `/api/v1/inbox/${replyId}/draft`, apiKey, {\n query: { channel },\n });\n return resp.data ?? (resp as unknown as InboxDraft);\n },\n\n /** Send a reply through email, SMS, or LinkedIn. */\n async send(replyId: string, payload: InboxSendParams): Promise<InboxSendResult> {\n const resp = await request<{ data?: InboxSendResult }>(baseUrl, `/api/v1/inbox/${replyId}/send`, apiKey, {\n method: \"POST\",\n body: payload,\n });\n return resp.data ?? (resp as unknown as InboxSendResult);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface QuoteLineItem {\n product_id?: string | null;\n name?: string | null;\n description?: string | null;\n quantity: number;\n unit_price: number;\n currency?: string | null;\n recurring?: boolean | null;\n}\n\nexport type QuoteStatus = \"draft\" | \"sent\" | \"signed\" | \"declined\" | \"expired\" | \"void\";\n\nexport interface QuoteSummary {\n id: string;\n name: string | null;\n status: QuoteStatus;\n total: number | null;\n currency: string | null;\n contact_id: number | null;\n company_id: number | null;\n expires_at: string | null;\n created_at: string | null;\n updated_at: string | null;\n signing_url: string | null;\n payment_link_url: string | null;\n}\n\nexport interface QuoteDetail extends QuoteSummary {\n line_items: QuoteLineItem[];\n notes: string | null;\n recipient_email: string | null;\n signed_at: string | null;\n sent_at: string | null;\n}\n\nexport interface QuoteCreateParams {\n contact_id?: number;\n company_id?: number;\n line_items: QuoteLineItem[];\n currency?: string;\n notes?: string;\n /** ISO 8601 timestamp. */\n expires_at?: string;\n name?: string;\n}\n\nexport interface QuoteUpdateParams {\n line_items?: QuoteLineItem[];\n notes?: string;\n expires_at?: string;\n name?: string;\n}\n\nexport interface QuoteSendParams {\n recipient_email: string;\n /** Whether to attach the signing link. Defaults to true. */\n send_signing_link?: boolean;\n}\n\nexport interface QuoteListParams {\n status?: QuoteStatus;\n contact_id?: number;\n company_id?: number;\n page?: number;\n limit?: number;\n}\n\nexport interface QuotableProduct {\n id: string;\n name: string;\n description: string | null;\n unit_price: number;\n currency: string;\n recurring: boolean;\n}\n\nexport interface QuoteSettings {\n default_currency: string;\n default_tax_rate: number | null;\n payment_providers: string[];\n logo_url: string | null;\n signature_required: boolean;\n}\n\nexport interface PaginationMeta {\n page: number;\n limit: number;\n total: number;\n has_next: boolean;\n}\n\n/**\n * Quotes API - quote-to-cash lifecycle. Requires API key (server-side). On the\n * hardened HTTP core: throws a typed `G8Error` on failure and retries transient\n * errors.\n *\n * Backed by:\n * GET /api/v1/quotes\n * GET /api/v1/quotes/{id}\n * POST /api/v1/quotes\n * PUT /api/v1/quotes/{id}\n * DELETE /api/v1/quotes/{id}\n * POST /api/v1/quotes/{id}/duplicate\n * POST /api/v1/quotes/{id}/edit-as-draft\n * POST /api/v1/quotes/{id}/send\n * GET /api/v1/quotable-products\n * GET /api/v1/quote-settings\n * GET /api/v1/contacts/{contact_id}/quotes\n * GET /api/v1/companies/{company_id}/quotes\n */\nexport const createQuotesClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** List quotes org-wide with optional filters and pagination. */\n async list(params: QuoteListParams = {}): Promise<{ data: QuoteSummary[]; pagination?: PaginationMeta }> {\n return request(baseUrl, \"/api/v1/quotes\", apiKey, { query: params as Record<string, unknown> });\n },\n\n /** Get full details for a single quote. */\n async get(quoteId: string): Promise<QuoteDetail> {\n const resp = await request<{ data?: QuoteDetail }>(baseUrl, `/api/v1/quotes/${quoteId}`, apiKey);\n return resp.data ?? (resp as unknown as QuoteDetail);\n },\n\n /** Create a new quote from line items. */\n async create(quote: QuoteCreateParams): Promise<QuoteDetail> {\n const resp = await request<{ data?: QuoteDetail }>(baseUrl, \"/api/v1/quotes\", apiKey, {\n method: \"POST\",\n body: quote,\n });\n return resp.data ?? (resp as unknown as QuoteDetail);\n },\n\n /** Update a draft quote (line items, expiry, notes). */\n async update(quoteId: string, fields: QuoteUpdateParams): Promise<QuoteDetail> {\n const resp = await request<{ data?: QuoteDetail }>(baseUrl, `/api/v1/quotes/${quoteId}`, apiKey, {\n method: \"PUT\",\n body: fields,\n });\n return resp.data ?? (resp as unknown as QuoteDetail);\n },\n\n /** Delete a draft quote (irreversible). */\n async delete(quoteId: string): Promise<{ data: { deleted: boolean } }> {\n return request(baseUrl, `/api/v1/quotes/${quoteId}`, apiKey, { method: \"DELETE\" });\n },\n\n /** Duplicate an existing quote (all line items copied into a new draft). */\n async duplicate(quoteId: string): Promise<QuoteDetail> {\n const resp = await request<{ data?: QuoteDetail }>(baseUrl, `/api/v1/quotes/${quoteId}/duplicate`, apiKey, {\n method: \"POST\",\n body: {},\n });\n return resp.data ?? (resp as unknown as QuoteDetail);\n },\n\n /** Convert a signed / sent quote back to editable draft state. */\n async editAsDraft(quoteId: string): Promise<{ data: { id: string; status: string } }> {\n return request(baseUrl, `/api/v1/quotes/${quoteId}/edit-as-draft`, apiKey, { method: \"POST\", body: {} });\n },\n\n /** Send a quote to its recipient via email (with signature + optional payment link). */\n async send(quoteId: string, params: QuoteSendParams): Promise<QuoteDetail> {\n const resp = await request<{ data?: QuoteDetail }>(baseUrl, `/api/v1/quotes/${quoteId}/send`, apiKey, {\n method: \"POST\",\n body: params,\n });\n return resp.data ?? (resp as unknown as QuoteDetail);\n },\n\n /** List products available for line items. */\n async products(): Promise<{ data: QuotableProduct[] }> {\n return request(baseUrl, \"/api/v1/quotable-products\", apiKey);\n },\n\n /** Get org-level quote settings (currency, tax rate, payment providers, logo). */\n async settings(): Promise<QuoteSettings> {\n const resp = await request<{ data?: QuoteSettings }>(baseUrl, \"/api/v1/quote-settings\", apiKey);\n return resp.data ?? (resp as unknown as QuoteSettings);\n },\n\n /** Get all quotes associated with a contact. */\n async forContact(contactId: number): Promise<{ data: QuoteSummary[] }> {\n return request(baseUrl, `/api/v1/contacts/${contactId}/quotes`, apiKey);\n },\n\n /** Get all quotes associated with a company. */\n async forCompany(companyId: number): Promise<{ data: QuoteSummary[] }> {\n return request(baseUrl, `/api/v1/companies/${companyId}/quotes`, apiKey);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\n/**\n * Stage Checklist v2 pipelines. A \"pipeline\" here is a multi-stage workflow\n * (with evidence requirements and per-channel scripts) that lives parallel\n * to deal pipelines. Use `g8.deals.pipelines()` for deal-pipeline reads.\n */\nexport interface StagePipelineStage {\n id: string;\n name: string;\n position: number;\n /** Evidence keys that must be collected before the stage can be marked done. */\n required_elements: string[];\n /** Evidence keys that are recommended but not enforced. */\n recommended_elements: string[];\n /** Channel-specific scripts (call, email, linkedin, etc.). */\n channel_scripts: Record<string, string>;\n color: string | null;\n stage_type: string | null;\n}\n\nexport interface StagePipeline {\n id: string;\n name: string;\n target: string | null;\n is_default: boolean;\n stages: StagePipelineStage[];\n created_at: string | null;\n updated_at: string | null;\n}\n\nexport interface StagePipelineCreateParams {\n name: string;\n target?: string;\n /** If true, creates an empty pipeline (no default stages). */\n blank?: boolean;\n}\n\nexport interface StagePipelineUpdateParams {\n name?: string;\n target?: string;\n}\n\nexport interface StageCreateParams {\n name: string;\n position?: number;\n required_elements?: string[];\n recommended_elements?: string[];\n channel_scripts?: Record<string, string>;\n color?: string;\n stage_type?: string;\n}\n\nexport interface StageUpdateParams {\n name?: string;\n position?: number;\n required_elements?: string[];\n recommended_elements?: string[];\n channel_scripts?: Record<string, string>;\n color?: string;\n}\n\nexport interface EvidenceKey {\n key: string;\n label: string;\n description: string;\n category: string;\n}\n\nexport interface PipelineSuggestion {\n suggestion_id: string;\n name: string;\n target: string;\n stages: Array<{ name: string; required_elements: string[]; channel_scripts: Record<string, string> }>;\n rationale: string;\n}\n\n/**\n * Stage Checklist Pipelines API - workflow pipelines with evidence + scripts.\n * Requires API key (server-side). On the hardened HTTP core: throws a typed\n * `G8Error` on failure and retries transient errors.\n *\n * Backed by:\n * GET /api/v1/pipelines\n * GET /api/v1/pipelines/{id}\n * GET /api/v1/pipelines/evidence-library\n * POST /api/v1/pipelines\n * PUT /api/v1/pipelines/{id}\n * DELETE /api/v1/pipelines/{id}\n * POST /api/v1/pipelines/{id}/stages\n * PUT /api/v1/pipelines/{id}/stages/{stage_id}\n * DELETE /api/v1/pipelines/{id}/stages/{stage_id}\n * PUT /api/v1/pipelines/{id}/stages/reorder\n * POST /api/v1/pipelines/suggest\n * POST /api/v1/pipelines/from-suggestion\n */\nexport const createPipelinesClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** List all stage-checklist pipelines with stages, evidence, scripts. */\n async list(): Promise<{ data: StagePipeline[] }> {\n return request(baseUrl, \"/api/v1/pipelines\", apiKey);\n },\n\n /** Get a single pipeline by ID. */\n async get(pipelineId: string): Promise<StagePipeline> {\n const resp = await request<{ data?: StagePipeline }>(baseUrl, `/api/v1/pipelines/${pipelineId}`, apiKey);\n return resp.data ?? (resp as unknown as StagePipeline);\n },\n\n /** Get the canonical evidence-key library (used when defining stages). */\n async evidenceLibrary(): Promise<{ data: EvidenceKey[] }> {\n return request(baseUrl, \"/api/v1/pipelines/evidence-library\", apiKey);\n },\n\n /** Create a new pipeline. Defaults to a templated set of stages; pass blank=true for empty. */\n async create(params: StagePipelineCreateParams): Promise<StagePipeline> {\n const resp = await request<{ data?: StagePipeline }>(baseUrl, \"/api/v1/pipelines\", apiKey, {\n method: \"POST\",\n body: params,\n });\n return resp.data ?? (resp as unknown as StagePipeline);\n },\n\n /** Update pipeline metadata (name, target). */\n async update(pipelineId: string, fields: StagePipelineUpdateParams): Promise<StagePipeline> {\n const resp = await request<{ data?: StagePipeline }>(baseUrl, `/api/v1/pipelines/${pipelineId}`, apiKey, {\n method: \"PUT\",\n body: fields,\n });\n return resp.data ?? (resp as unknown as StagePipeline);\n },\n\n /** Delete a pipeline. Only allowed when no deals reference it. */\n async delete(pipelineId: string): Promise<{ data: { deleted: boolean } }> {\n return request(baseUrl, `/api/v1/pipelines/${pipelineId}`, apiKey, { method: \"DELETE\" });\n },\n\n /** Add a new stage to a pipeline. */\n async createStage(pipelineId: string, stage: StageCreateParams): Promise<StagePipelineStage> {\n const resp = await request<{ data?: StagePipelineStage }>(\n baseUrl,\n `/api/v1/pipelines/${pipelineId}/stages`,\n apiKey,\n { method: \"POST\", body: stage },\n );\n return resp.data ?? (resp as unknown as StagePipelineStage);\n },\n\n /** Update a stage (evidence, scripts, position). */\n async updateStage(pipelineId: string, stageId: string, fields: StageUpdateParams): Promise<StagePipelineStage> {\n const resp = await request<{ data?: StagePipelineStage }>(\n baseUrl,\n `/api/v1/pipelines/${pipelineId}/stages/${stageId}`,\n apiKey,\n { method: \"PUT\", body: fields },\n );\n return resp.data ?? (resp as unknown as StagePipelineStage);\n },\n\n /** Reorder stages within a pipeline (pass full ordered list of stage IDs). */\n async reorderStages(pipelineId: string, stageIds: string[]): Promise<{ data: StagePipelineStage[] }> {\n return request(baseUrl, `/api/v1/pipelines/${pipelineId}/stages/reorder`, apiKey, {\n method: \"PUT\",\n body: { stage_ids: stageIds },\n });\n },\n\n /** Delete a stage from a pipeline. */\n async deleteStage(pipelineId: string, stageId: string): Promise<{ data: { deleted: boolean } }> {\n return request(baseUrl, `/api/v1/pipelines/${pipelineId}/stages/${stageId}`, apiKey, { method: \"DELETE\" });\n },\n\n /** Get an AI-suggested pipeline based on org context (brand, ICP, messaging). */\n async suggest(): Promise<{ data: PipelineSuggestion }> {\n return request(baseUrl, \"/api/v1/pipelines/suggest\", apiKey, { method: \"POST\", body: {} });\n },\n\n /** Create a real pipeline from an AI suggestion (optionally with overrides). */\n async fromSuggestion(\n suggestionId: string,\n overrides?: Partial<{ name: string; target: string }>,\n ): Promise<StagePipeline> {\n const resp = await request<{ data?: StagePipeline }>(baseUrl, \"/api/v1/pipelines/from-suggestion\", apiKey, {\n method: \"POST\",\n body: { suggestion_id: suggestionId, ...(overrides || {}) },\n });\n return resp.data ?? (resp as unknown as StagePipeline);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface WorkflowNode {\n id: string;\n type: string;\n config: Record<string, unknown>;\n position?: { x: number; y: number };\n /** Mapping from this node's output to the next node's input. */\n input_mappings?: Record<string, string>;\n}\n\nexport interface WorkflowConnection {\n from_node_id: string;\n to_node_id: string;\n condition?: string | null;\n}\n\nexport interface WorkflowConfig {\n nodes: WorkflowNode[];\n connections: WorkflowConnection[];\n trigger?: Record<string, unknown> | null;\n}\n\nexport interface Workflow {\n id: string;\n name: string;\n description: string | null;\n config: WorkflowConfig;\n trigger_config: Record<string, unknown> | null;\n is_active: boolean;\n created_at: string | null;\n updated_at: string | null;\n}\n\nexport interface WorkflowCreateParams {\n name: string;\n description?: string;\n config?: WorkflowConfig;\n trigger_config?: Record<string, unknown>;\n}\n\nexport interface WorkflowUpdateParams {\n name?: string;\n description?: string;\n config?: WorkflowConfig;\n trigger_config?: Record<string, unknown>;\n is_active?: boolean;\n}\n\nexport interface WorkflowExecution {\n id: string;\n workflow_id: string;\n status: \"pending\" | \"running\" | \"paused\" | \"completed\" | \"failed\" | \"stopped\";\n trigger_payload: Record<string, unknown>;\n outputs: Record<string, unknown>;\n error: string | null;\n started_at: string | null;\n ended_at: string | null;\n}\n\nexport interface NodeTypeSchema {\n type: string;\n label: string;\n description: string;\n config_schema: Record<string, unknown>;\n output_schema: Record<string, unknown>;\n}\n\nexport interface WorkflowListParams {\n page?: number;\n limit?: number;\n is_active?: boolean;\n search?: string;\n}\n\n/**\n * Workflows API - automation workflows with nodes, connections, and execution lifecycle.\n * Requires API key (server-side). On the hardened HTTP core: throws a typed\n * `G8Error` on failure and retries transient errors.\n *\n * The graph8 workflow surface treats the whole workflow definition as a single\n * record updated via `update()` — there are no per-node CRUD endpoints. To edit\n * nodes or connections, fetch the workflow, mutate `config.nodes` / `config.connections`,\n * and PUT it back.\n *\n * Backed by:\n * GET /api/v1/workflows\n * GET /api/v1/workflows/{id}\n * POST /api/v1/workflows\n * PUT /api/v1/workflows/{id}\n * DELETE /api/v1/workflows/{id}\n * POST /api/v1/workflows/validate\n * POST /api/v1/workflows/{id}/execute\n * GET /api/v1/workflows/executions/{exec_id}\n * POST /api/v1/workflows/executions/{exec_id}/pause\n * POST /api/v1/workflows/executions/{exec_id}/resume\n * POST /api/v1/workflows/executions/{exec_id}/stop\n * GET /api/v1/workflows/{id}/trigger-status\n * POST /api/v1/workflows/{id}/trigger-reset\n * GET /api/v1/workflows/node-types/schema\n * GET /api/v1/workflows/integrations/slack/users|channels\n * GET /api/v1/workflows/integrations/roam/users|groups\n * GET /api/v1/workflows/mcp-servers\n * GET /api/v1/workflows/dispositions\n * GET /api/v1/workflows/forms/{form_id}/fields\n */\nexport const createWorkflowsClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** List workflows org-wide. */\n async list(params: WorkflowListParams = {}): Promise<{ data: Workflow[] }> {\n return request(baseUrl, \"/api/v1/workflows\", apiKey, { query: params as Record<string, unknown> });\n },\n\n /** Get full workflow definition (nodes, connections, trigger, execution state). */\n async get(workflowId: string): Promise<Workflow> {\n const resp = await request<{ data?: Workflow }>(baseUrl, `/api/v1/workflows/${workflowId}`, apiKey);\n return resp.data ?? (resp as unknown as Workflow);\n },\n\n /** Create a new workflow. */\n async create(params: WorkflowCreateParams): Promise<Workflow> {\n const resp = await request<{ data?: Workflow }>(baseUrl, \"/api/v1/workflows\", apiKey, {\n method: \"POST\",\n body: params,\n });\n return resp.data ?? (resp as unknown as Workflow);\n },\n\n /**\n * Update a workflow. Pass the full `config` (nodes + connections) to edit\n * the graph — node-level CRUD is performed client-side by mutating the\n * config and submitting the updated record.\n */\n async update(workflowId: string, fields: WorkflowUpdateParams): Promise<Workflow> {\n const resp = await request<{ data?: Workflow }>(baseUrl, `/api/v1/workflows/${workflowId}`, apiKey, {\n method: \"PUT\",\n body: fields,\n });\n return resp.data ?? (resp as unknown as Workflow);\n },\n\n /** Delete a workflow. */\n async delete(workflowId: string): Promise<{ data: { deleted: boolean } }> {\n return request(baseUrl, `/api/v1/workflows/${workflowId}`, apiKey, { method: \"DELETE\" });\n },\n\n /** Validate a workflow definition (orphans, dangling connections, required fields). */\n async validate(workflow: { config: WorkflowConfig; trigger_config?: Record<string, unknown> }): Promise<{\n data: { valid: boolean; errors: Array<{ node_id?: string; field?: string; message: string }> };\n }> {\n return request(baseUrl, \"/api/v1/workflows/validate\", apiKey, { method: \"POST\", body: workflow });\n },\n\n /** Execute a workflow immediately with a trigger payload. */\n async execute(workflowId: string, triggerPayload: Record<string, unknown> = {}): Promise<WorkflowExecution> {\n const resp = await request<{ data?: WorkflowExecution }>(\n baseUrl,\n `/api/v1/workflows/${workflowId}/execute`,\n apiKey,\n { method: \"POST\", body: { trigger_payload: triggerPayload } },\n );\n return resp.data ?? (resp as unknown as WorkflowExecution);\n },\n\n /** Get the status + outputs of a single execution. */\n async getExecution(executionId: string): Promise<WorkflowExecution> {\n const resp = await request<{ data?: WorkflowExecution }>(\n baseUrl,\n `/api/v1/workflows/executions/${executionId}`,\n apiKey,\n );\n return resp.data ?? (resp as unknown as WorkflowExecution);\n },\n\n /** Pause a running execution. */\n async pauseExecution(executionId: string): Promise<{ data: { paused: boolean } }> {\n return request(baseUrl, `/api/v1/workflows/executions/${executionId}/pause`, apiKey, { method: \"POST\" });\n },\n\n /** Resume a paused execution. */\n async resumeExecution(executionId: string): Promise<{ data: { resumed: boolean } }> {\n return request(baseUrl, `/api/v1/workflows/executions/${executionId}/resume`, apiKey, { method: \"POST\" });\n },\n\n /** Stop an execution. */\n async stopExecution(executionId: string): Promise<{ data: { stopped: boolean } }> {\n return request(baseUrl, `/api/v1/workflows/executions/${executionId}/stop`, apiKey, { method: \"POST\" });\n },\n\n /** Get the trigger status (e.g. schedule / webhook wiring) for a workflow. */\n async getTriggerStatus(workflowId: string): Promise<{ data: { status: string; details: Record<string, unknown> } }> {\n return request(baseUrl, `/api/v1/workflows/${workflowId}/trigger-status`, apiKey);\n },\n\n /** Reset a workflow's trigger cursor / state. */\n async resetTrigger(workflowId: string): Promise<{ data: { reset: boolean } }> {\n return request(baseUrl, `/api/v1/workflows/${workflowId}/trigger-reset`, apiKey, { method: \"POST\" });\n },\n\n /** Catalog of available workflow node types with config + output schemas. */\n async nodeTypes(params: { type?: string } = {}): Promise<{ data: NodeTypeSchema[] }> {\n return request(baseUrl, \"/api/v1/workflows/node-types/schema\", apiKey, {\n query: params as Record<string, unknown>,\n });\n },\n\n /** Slack users available to workflow nodes. */\n async listSlackUsers(): Promise<{ data: Array<{ id: string; name: string; email: string | null }> }> {\n return request(baseUrl, \"/api/v1/workflows/integrations/slack/users\", apiKey);\n },\n\n /** Slack channels available to workflow nodes. */\n async listSlackChannels(): Promise<{ data: Array<{ id: string; name: string; is_private: boolean }> }> {\n return request(baseUrl, \"/api/v1/workflows/integrations/slack/channels\", apiKey);\n },\n\n /** Roam users available to workflow nodes. */\n async listRoamUsers(): Promise<{ data: Array<{ id: string; name: string; email: string | null }> }> {\n return request(baseUrl, \"/api/v1/workflows/integrations/roam/users\", apiKey);\n },\n\n /** Roam groups available to workflow nodes. */\n async listRoamGroups(): Promise<{ data: Array<{ id: string; name: string }> }> {\n return request(baseUrl, \"/api/v1/workflows/integrations/roam/groups\", apiKey);\n },\n\n /** MCP servers available to workflow nodes. */\n async listMcpServers(): Promise<{ data: Array<{ id: string; name: string; url: string }> }> {\n return request(baseUrl, \"/api/v1/workflows/mcp-servers\", apiKey);\n },\n\n /** Disposition options available to workflow nodes. */\n async listDispositions(): Promise<{ data: Array<{ id: string; label: string }> }> {\n return request(baseUrl, \"/api/v1/workflows/dispositions\", apiKey);\n },\n\n /** Form field definitions for a given form (used by form-trigger nodes). */\n async listFormFields(formId: string): Promise<{ data: Array<{ name: string; type: string; required: boolean }> }> {\n return request(baseUrl, `/api/v1/workflows/forms/${formId}/fields`, apiKey);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport type SkillType = \"llm\" | \"api\";\n\nexport interface SkillInputField {\n name: string;\n type: string;\n required: boolean;\n description?: string;\n}\n\nexport interface Skill {\n id: string;\n title: string;\n description: string | null;\n type: SkillType;\n /** Only present on `type=llm`. */\n prompt?: string;\n /** Only present on `type=llm`. */\n model?: string;\n /** Only present on `type=api`. */\n method?: \"GET\" | \"POST\" | \"PATCH\" | \"PUT\" | \"DELETE\";\n /** Only present on `type=api`. */\n url?: string;\n /** Only present on `type=api`. */\n headers?: Record<string, string>;\n /** Only present on `type=api`. */\n body_template?: string;\n input_schema: { fields: SkillInputField[] };\n output_schema: Record<string, unknown> | null;\n created_at: string | null;\n updated_at: string | null;\n}\n\nexport interface SkillCreateLLMParams {\n title: string;\n description?: string;\n prompt: string;\n model: string;\n input_schema: { fields: SkillInputField[] };\n output_schema?: Record<string, unknown>;\n}\n\nexport interface SkillCreateAPIParams {\n title: string;\n description?: string;\n method: \"GET\" | \"POST\" | \"PATCH\" | \"PUT\" | \"DELETE\";\n url: string;\n headers?: Record<string, string>;\n body_template?: string;\n response_mapping?: Record<string, string>;\n input_schema: { fields: SkillInputField[] };\n}\n\nexport interface SkillUpdateLLMParams {\n title?: string;\n description?: string;\n prompt?: string;\n model?: string;\n input_schema?: { fields: SkillInputField[] };\n output_schema?: Record<string, unknown>;\n}\n\nexport interface SkillUpdateAPIParams {\n title?: string;\n description?: string;\n method?: \"GET\" | \"POST\" | \"PATCH\" | \"PUT\" | \"DELETE\";\n url?: string;\n headers?: Record<string, string>;\n body_template?: string;\n response_mapping?: Record<string, string>;\n input_schema?: { fields: SkillInputField[] };\n}\n\nexport interface SkillTemplate {\n id: string;\n title: string;\n description: string;\n type: SkillType;\n use_cases: string[];\n}\n\nexport interface SkillListParams {\n page?: number;\n limit?: number;\n type?: SkillType;\n search?: string;\n}\n\n/**\n * Skills API - LLM and API building blocks that workflows compose into runs.\n * Requires API key (server-side).\n *\n * Backed by:\n * GET /api/v1/skills\n * GET /api/v1/skills/{id}\n * GET /api/v1/skills/{id}/variables\n * GET /api/v1/skills/models\n * GET /api/v1/skills/templates\n * POST /api/v1/skills (both llm + api types via `type` field)\n * POST /api/v1/skills/from-template\n * POST /api/v1/skills/from-node\n * PUT /api/v1/skills/{id}\n * DELETE /api/v1/skills/{id}\n * POST /api/v1/skills/validate\n * POST /api/v1/skills/{id}/execute\n */\nexport const createSkillsClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n return {\n /** List skills. */\n async list(params: SkillListParams = {}): Promise<{ data: Skill[] }> {\n return request(baseUrl, \"/api/v1/skills\", apiKey, { query: params as Record<string, unknown> });\n },\n\n /** Get a skill by ID. */\n async get(skillId: string): Promise<Skill> {\n const resp = await request<{ data?: Skill }>(baseUrl, `/api/v1/skills/${skillId}`, apiKey);\n return resp.data ?? (resp as unknown as Skill);\n },\n\n /** Get the variables required by a skill (extracted from prompt or body template). */\n async getVariables(skillId: string): Promise<{ data: SkillInputField[] }> {\n return request(baseUrl, `/api/v1/skills/${skillId}/variables`, apiKey);\n },\n\n /** List available LLM models. */\n async listModels(): Promise<{ data: Array<{ id: string; label: string; provider: string }> }> {\n return request(baseUrl, \"/api/v1/skills/models\", apiKey);\n },\n\n /** List skill templates. */\n async listTemplates(params: { type?: SkillType } = {}): Promise<{ data: SkillTemplate[] }> {\n return request(baseUrl, \"/api/v1/skills/templates\", apiKey, { query: params as Record<string, unknown> });\n },\n\n /** Create an LLM skill (prompt + model + schemas). */\n async createLLM(params: SkillCreateLLMParams): Promise<Skill> {\n const resp = await request<{ data?: Skill }>(baseUrl, \"/api/v1/skills\", apiKey, {\n method: \"POST\",\n body: { ...params, type: \"llm\" },\n });\n return resp.data ?? (resp as unknown as Skill);\n },\n\n /** Create an API skill (HTTP request wrapper). */\n async createAPI(params: SkillCreateAPIParams): Promise<Skill> {\n const resp = await request<{ data?: Skill }>(baseUrl, \"/api/v1/skills\", apiKey, {\n method: \"POST\",\n body: { ...params, type: \"api\" },\n });\n return resp.data ?? (resp as unknown as Skill);\n },\n\n /** Create a skill from a built-in template. */\n async createFromTemplate(params: { title: string; template_id: string; overrides?: Record<string, unknown> }): Promise<Skill> {\n const resp = await request<{ data?: Skill }>(baseUrl, \"/api/v1/skills/from-template\", apiKey, {\n method: \"POST\",\n body: params,\n });\n return resp.data ?? (resp as unknown as Skill);\n },\n\n /** Lift a workflow node into a reusable skill. */\n async createFromNode(params: {\n title: string;\n description?: string;\n node_id: string;\n input_mapping?: Record<string, string>;\n output_mapping?: Record<string, string>;\n }): Promise<Skill> {\n const resp = await request<{ data?: Skill }>(baseUrl, \"/api/v1/skills/from-node\", apiKey, {\n method: \"POST\",\n body: params,\n });\n return resp.data ?? (resp as unknown as Skill);\n },\n\n /** Update an LLM skill. */\n async updateLLM(skillId: string, fields: SkillUpdateLLMParams): Promise<Skill> {\n const resp = await request<{ data?: Skill }>(baseUrl, `/api/v1/skills/${skillId}`, apiKey, {\n method: \"PUT\",\n body: { ...fields, type: \"llm\" },\n });\n return resp.data ?? (resp as unknown as Skill);\n },\n\n /** Update an API skill. */\n async updateAPI(skillId: string, fields: SkillUpdateAPIParams): Promise<Skill> {\n const resp = await request<{ data?: Skill }>(baseUrl, `/api/v1/skills/${skillId}`, apiKey, {\n method: \"PUT\",\n body: { ...fields, type: \"api\" },\n });\n return resp.data ?? (resp as unknown as Skill);\n },\n\n /** Delete a skill (irreversible if in-use workflows exist). */\n async delete(skillId: string): Promise<{ data: { deleted: boolean } }> {\n return request(baseUrl, `/api/v1/skills/${skillId}`, apiKey, { method: \"DELETE\" });\n },\n\n /** Validate a skill definition (without saving). */\n async validate(skill: Partial<Skill>): Promise<{ data: { valid: boolean; errors: string[] } }> {\n return request(baseUrl, \"/api/v1/skills/validate\", apiKey, { method: \"POST\", body: skill });\n },\n\n /** Execute a skill immediately with an input payload (test / preview). */\n async execute(skillId: string, inputPayload: Record<string, unknown>): Promise<{\n data: { output: Record<string, unknown>; latency_ms: number; tokens?: number; error: string | null };\n }> {\n return request(baseUrl, `/api/v1/skills/${skillId}/execute`, apiKey, { method: \"POST\", body: inputPayload });\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface IntentKeyword {\n id: string;\n keyword: string;\n domain: string | null;\n include_patterns: string[];\n exclude_patterns: string[];\n page_count: number;\n visitor_count: number;\n company_count: number;\n contact_count: number;\n created_at: string | null;\n}\n\nexport interface IntentPage {\n url: string;\n title: string | null;\n keyword: string | null;\n domain: string;\n visitor_count: number;\n last_seen: string | null;\n}\n\nexport interface IntentVisitor {\n visitor_id: string;\n company_domain: string | null;\n company_name: string | null;\n page_url: string;\n first_seen: string | null;\n last_seen: string | null;\n visit_count: number;\n}\n\nexport interface IntentCompany {\n domain: string;\n name: string | null;\n industry: string | null;\n employee_count: string | null;\n visit_count: number;\n last_seen: string | null;\n}\n\nexport interface IntentContact {\n contact_id: number | null;\n email: string | null;\n full_name: string | null;\n company: string | null;\n job_title: string | null;\n last_seen: string | null;\n}\n\nexport interface IntentStats {\n total_keywords: number;\n total_pages: number;\n total_visitors_30d: number;\n total_companies_30d: number;\n}\n\n/**\n * Intent + visitor tracking. Distinct from `g8.signals` (which is summary scoring) —\n * this module exposes keyword tracking, page-level visitor data, and account-level\n * intent signals from your own site (or from competitor URLs you've added).\n *\n * Requires API key (server-side).\n *\n * Backed by:\n * GET /api/v1/intent/stats\n * POST /api/v1/intent/keywords/list\n * POST /api/v1/intent/keywords/create-from-domain\n * DELETE /api/v1/intent/keywords/{keyword_id}\n * POST /api/v1/intent/keywords/{keyword_id}/companies\n * POST /api/v1/intent/keywords/{keyword_id}/contacts\n * POST /api/v1/intent/keywords/{keyword_id}/urls\n * POST /api/v1/intent/pages-by-domain\n * POST /api/v1/intent/pages/search\n * POST /api/v1/intent/pages/visitors\n * POST /api/v1/intent/pages/contacts\n * POST /api/v1/intent/pages/visitor-counts\n * POST /intent-search/url-companies (note: bare host, no /api/v1 prefix)\n */\nexport const createIntentClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n const get = (path: string) => request<any>(baseUrl, `/api/v1${path}`, apiKey);\n const post = (path: string, body: Record<string, unknown> = {}) =>\n request<any>(baseUrl, `/api/v1${path}`, apiKey, { method: \"POST\", body });\n const del = (path: string) => request<any>(baseUrl, `/api/v1${path}`, apiKey, { method: \"DELETE\" });\n\n return {\n /** Org-level intent stats (totals over the last 30 days). */\n async stats(): Promise<{ data: IntentStats }> {\n return get(\"/intent/stats\");\n },\n\n /** List tracked keywords with optional pagination. */\n async listKeywords(params: { page?: number; limit?: number; search?: string } = {}): Promise<{ data: IntentKeyword[] }> {\n return post(\"/intent/keywords/list\", params);\n },\n\n /** Create a keyword group from a domain (auto-tracks all pages). */\n async createFromDomain(domain: string): Promise<{ data: IntentKeyword }> {\n return post(\"/intent/keywords/create-from-domain\", { domain });\n },\n\n /** Stop tracking a keyword (irreversible — historical data is retained). */\n async deleteKeyword(keywordId: string): Promise<{ data: { deleted: boolean } }> {\n return del(`/intent/keywords/${keywordId}`);\n },\n\n /** Companies showing interest in a tracked keyword. */\n async keywordCompanies(keywordId: string, params: { limit?: number; date_from?: string; date_to?: string } = {}): Promise<{ data: IntentCompany[] }> {\n return post(`/intent/keywords/${keywordId}/companies`, params);\n },\n\n /** Contacts showing interest in a tracked keyword. */\n async keywordContacts(keywordId: string, params: { limit?: number; date_from?: string; date_to?: string } = {}): Promise<{ data: IntentContact[] }> {\n return post(`/intent/keywords/${keywordId}/contacts`, params);\n },\n\n /** URLs associated with a keyword (pages visitors landed on while interested). */\n async keywordUrls(keywordId: string, params: { limit?: number } = {}): Promise<{ data: IntentPage[] }> {\n return post(`/intent/keywords/${keywordId}/urls`, params);\n },\n\n /** Pages tracked on a specific domain. */\n async pagesByDomain(domain: string, params: { limit?: number } = {}): Promise<{ data: IntentPage[] }> {\n return post(\"/intent/pages-by-domain\", { domain, ...params });\n },\n\n /** Search tracked pages by URL fragment or keyword. */\n async searchPages(query: string, params: { limit?: number } = {}): Promise<{ data: IntentPage[] }> {\n return post(\"/intent/pages/search\", { query, ...params });\n },\n\n /** Get visitor records for a specific page URL. */\n async pageVisitors(pageUrl: string, params: { limit?: number; date_from?: string; date_to?: string } = {}): Promise<{ data: IntentVisitor[] }> {\n return post(\"/intent/pages/visitors\", { url: pageUrl, ...params });\n },\n\n /** Get contacts who visited a specific page URL. */\n async pageContacts(pageUrl: string, params: { limit?: number } = {}): Promise<{ data: IntentContact[] }> {\n return post(\"/intent/pages/contacts\", { url: pageUrl, ...params });\n },\n\n /** Visitor count aggregates by page (pass an array of URLs). */\n async pageVisitorCounts(urls: string[]): Promise<{ data: Array<{ url: string; visitor_count: number }> }> {\n return post(\"/intent/pages/visitor-counts\", { urls });\n },\n\n /**\n * Find companies whose users visited a specific URL (intent search).\n *\n * Note: this endpoint lives at the bare host (no `/api/v1` prefix), unlike the rest\n * of the intent surface — we call it directly here instead of through the shared `post()` helper.\n */\n async urlCompanies(url: string, params: { limit?: number; date_from?: string; date_to?: string } = {}): Promise<{ data: IntentCompany[] }> {\n return request<{ data: IntentCompany[] }>(baseUrl, \"/intent-search/url-companies\", apiKey, {\n method: \"POST\",\n body: { url, ...params },\n });\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface GlobalContextDocument {\n id: string;\n category: string;\n title: string;\n content: string;\n metadata: Record<string, unknown> | null;\n created_at: string | null;\n updated_at: string | null;\n}\n\nexport interface Persona {\n id: string;\n name: string;\n description: string | null;\n status: string;\n pain_points: string[];\n goals: string[];\n channels: string[];\n created_at: string | null;\n}\n\nexport interface ICP {\n id: string;\n name: string;\n description: string | null;\n status: string;\n industry: string[] | null;\n employee_count_min: number | null;\n employee_count_max: number | null;\n revenue_min: number | null;\n revenue_max: number | null;\n countries: string[] | null;\n created_at: string | null;\n}\n\nexport interface IntelligenceData {\n id: string;\n source_type: string;\n url: string | null;\n title: string | null;\n content_summary: string | null;\n collected_at: string | null;\n}\n\nexport interface ResearchReport {\n id: string;\n category: \"buyer_psychology\" | \"competitive_teardown\" | \"gtm_channel\" | \"industry_analyst\" | \"review_sentiment\" | \"voice_of_customer\";\n title: string;\n summary: string | null;\n created_at: string | null;\n}\n\n/**\n * Studio context — org-level intelligence documents. The 44-doc engine that\n * powers campaign ideation: brand brief, value props, messaging house, ICPs,\n * personas, intelligence (scrapes + enrichment), and AI research reports.\n *\n * Requires API key (server-side).\n *\n * Backed by:\n * GET /api/v1/global-context/documents\n * GET /api/v1/icps\n * GET /api/v1/personas\n * GET /api/v1/intelligence-data\n * GET /api/v1/research-reports\n */\nexport const createStudioClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n const get = (path: string, params: object = {}) =>\n request<any>(baseUrl, `/api/v1${path}`, apiKey, { query: params as Record<string, unknown> });\n\n return {\n /** Org-level Studio documents (brand_brief, value_props, messaging_house, etc.).\n * `include_content` defaults to true server-side, so each document includes\n * its `content` body unless you explicitly pass `include_content: false`. */\n async globalContext(\n params: { category?: string; limit?: number; include_content?: boolean } = {}\n ): Promise<{ data: GlobalContextDocument[] }> {\n return get(\"/global-context/documents\", params);\n },\n\n /** ICP definitions. */\n async icps(params: { status?: string; limit?: number } = {}): Promise<{ data: ICP[] }> {\n return get(\"/icps\", params);\n },\n\n /** Buyer persona definitions. */\n async personas(params: { status?: string; limit?: number } = {}): Promise<{ data: Persona[] }> {\n return get(\"/personas\", params);\n },\n\n /** Intelligence data (website scrapes, enrichment, competitor research). */\n async intelligenceData(params: { source_type?: string; limit?: number } = {}): Promise<{ data: IntelligenceData[] }> {\n return get(\"/intelligence-data\", params);\n },\n\n /** AI research reports (buyer psychology, competitive teardown, GTM channel, etc.). */\n async researchReports(params: { category?: string; limit?: number } = {}): Promise<{ data: ResearchReport[] }> {\n return get(\"/research-reports\", params);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface MeetingAttendee {\n name: string | null;\n email: string;\n role: \"host\" | \"prospect\" | \"guest\" | string;\n contact_id?: number | null;\n}\n\nexport interface MeetingTranscriptLine {\n speaker: string;\n text: string;\n timestamp: number;\n}\n\nexport interface MeetingAnalysis {\n sentiment: \"positive\" | \"neutral\" | \"negative\";\n summary: string;\n next_steps: string[];\n objections: string[];\n talk_listen_ratio: number | null;\n}\n\nexport interface MeetingSummary {\n id: string;\n status: \"scheduled\" | \"completed\" | \"cancelled\" | \"no_show\";\n event_type: string | null;\n scheduled_at: string;\n duration_minutes: number;\n attendees: MeetingAttendee[];\n contact_id: number | null;\n conferencing_provider: string | null;\n conferencing_url: string | null;\n recording_url: string | null;\n created_at: string;\n}\n\nexport interface MeetingDetail extends MeetingSummary {\n transcript: MeetingTranscriptLine[] | null;\n analysis: MeetingAnalysis | null;\n}\n\nexport interface MeetingListParams {\n status?: \"scheduled\" | \"completed\" | \"cancelled\" | \"no_show\";\n date_from?: string;\n date_to?: string;\n attendee_id?: string;\n event_type?: string;\n contact_id?: number;\n page?: number;\n limit?: number;\n}\n\n/**\n * Meetings API - read-only access to scheduled, completed, and cancelled meetings.\n * Booking happens via `g8.calendar.*` (write-key safe, browser only) — this surface\n * is for reading meeting records, transcripts, and AI analysis.\n *\n * Requires API key (server-side).\n *\n * Backed by:\n * GET /api/v1/inbox/meetings\n * GET /api/v1/inbox/meetings/{meeting_id}\n */\nexport const createMeetingsClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** List meetings with optional filters. Returns summary rows without transcript / analysis. */\n async list(params: MeetingListParams = {}): Promise<{ data: MeetingSummary[]; pagination?: { page: number; limit: number; total: number; has_next: boolean } }> {\n return request(baseUrl, \"/api/v1/inbox/meetings\", apiKey, { query: params as Record<string, unknown> });\n },\n\n /** Get full meeting detail including transcript + AI analysis (transcript available 1-5 min after meeting ends). */\n async get(meetingId: string): Promise<MeetingDetail> {\n const resp = await request<{ data?: MeetingDetail }>(baseUrl, `/api/v1/inbox/meetings/${meetingId}`, apiKey);\n return resp.data ?? (resp as unknown as MeetingDetail);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\n/** Ad platform an audience can sync to. */\nexport type AudienceSyncPlatform = \"meta\" | \"linkedin\" | \"google\" | \"x\";\n/** Sync mode: full mirror, or only ever add members. */\nexport type AudienceSyncMode = \"mirror\" | \"append_only\";\n\nexport interface AudienceSync {\n id: number;\n audience_id: number;\n platform: string;\n platform_audience_name: string | null;\n mode: string;\n refresh_cadence_hours: number;\n is_active: boolean;\n status: string | null;\n last_sync_at: string | null;\n created_at: string | null;\n}\n\nexport interface AudienceSyncCreateParams {\n /** Audience list ID to sync. */\n audience_id: number;\n platform: AudienceSyncPlatform;\n platform_audience_name?: string;\n /** Default \"mirror\". */\n mode?: AudienceSyncMode;\n /** Refresh cadence in hours (0-720; default 24). */\n refresh_cadence_hours?: number;\n /** Platform-specific config (OAuth creds, ad-account ids, etc.). */\n platform_config?: Record<string, unknown>;\n /** Audience list IDs whose members should be suppressed from the sync. */\n suppression_list_ids?: number[];\n}\n\nexport interface AudienceSyncUpdateParams {\n mode?: AudienceSyncMode;\n refresh_cadence_hours?: number;\n is_active?: boolean;\n suppression_list_ids?: number[];\n}\n\nexport interface AudienceSyncRun {\n id: number;\n started_at: string | null;\n finished_at: string | null;\n status: string | null;\n members_added: number | null;\n members_removed: number | null;\n total_members: number | null;\n error_message: string | null;\n}\n\nexport interface AudienceSyncError {\n id: number;\n started_at: string | null;\n error_message: string | null;\n details: Record<string, unknown> | null;\n}\n\n/**\n * Audiences API — sync an audience list to ad platforms (Meta, LinkedIn,\n * Google, X). Requires API key (server-side). Built on the hardened HTTP core,\n * so every method throws a typed `G8Error` on failure and retries transient\n * 429/5xx/network errors.\n *\n * Backed by `/api/v1/audience-syncs`.\n */\nexport const createAudiencesClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n const base = \"/api/v1/audience-syncs\";\n\n return {\n /** List all audience syncs for the organization. */\n async list(): Promise<{ data: AudienceSync[] }> {\n return request(baseUrl, base, apiKey);\n },\n\n /** Create a new audience sync to an ad platform. */\n async create(params: AudienceSyncCreateParams): Promise<AudienceSync> {\n const resp = await request<{ data?: AudienceSync }>(baseUrl, base, apiKey, {\n method: \"POST\",\n body: params,\n });\n return resp.data ?? (resp as unknown as AudienceSync);\n },\n\n /** Get a single audience sync by ID. */\n async get(configId: number): Promise<AudienceSync> {\n const resp = await request<{ data?: AudienceSync }>(baseUrl, `${base}/${configId}`, apiKey);\n return resp.data ?? (resp as unknown as AudienceSync);\n },\n\n /** Update an audience sync (partial). */\n async update(configId: number, fields: AudienceSyncUpdateParams): Promise<AudienceSync> {\n const resp = await request<{ data?: AudienceSync }>(baseUrl, `${base}/${configId}`, apiKey, {\n method: \"PATCH\",\n body: fields,\n });\n return resp.data ?? (resp as unknown as AudienceSync);\n },\n\n /** Delete an audience sync. */\n async delete(configId: number): Promise<{ data: Record<string, unknown> }> {\n return request(baseUrl, `${base}/${configId}`, apiKey, { method: \"DELETE\" });\n },\n\n /** Trigger an immediate sync run for a config. */\n async trigger(configId: number): Promise<{ data: Record<string, unknown> }> {\n return request(baseUrl, `${base}/${configId}/trigger`, apiKey, { method: \"POST\" });\n },\n\n /** List recent sync runs for a config (most recent first). */\n async runs(configId: number): Promise<{ data: AudienceSyncRun[] }> {\n return request(baseUrl, `${base}/${configId}/runs`, apiKey);\n },\n\n /** List recent sync errors for a config. */\n async errors(configId: number): Promise<{ data: AudienceSyncError[] }> {\n return request(baseUrl, `${base}/${configId}/errors`, apiKey);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\n/** Filter operators supported by open-data search. */\nexport type SearchOperator =\n | \"any_of\"\n | \"contains\"\n | \"all_of\"\n | \"none_of\"\n | \"is_empty\"\n | \"is_not_empty\"\n | \"between\"\n | \"exists\";\n\n/** A single search filter condition (named to avoid colliding with enrich's `SearchFilter`). */\nexport interface SearchCondition {\n /** Field to filter on, e.g. \"job_title\", \"country\", \"industry\". */\n field: string;\n operator: SearchOperator;\n /** Filter values (operator-dependent; e.g. `[\"VP\", \"Director\"]` for any_of). */\n value?: unknown[];\n}\n\nexport interface SearchParams {\n /** Filter conditions, combined with AND. */\n filters?: SearchCondition[];\n /** Page number, 1-indexed (1-100). */\n page?: number;\n /** Results per page (1-100, default 25). */\n limit?: number;\n}\n\nexport interface SearchSaveParams extends SearchParams {\n /** Title for the new list the matched records are saved into. */\n list_title: string;\n /** Max records to save (1-10,000, default 1,000). */\n max_results?: number;\n}\n\nexport interface SearchContactItem {\n first_name?: string | null;\n last_name?: string | null;\n middle_name?: string | null;\n work_email?: string | null;\n personal_emails?: string | null;\n direct_phone?: string | null;\n mobile_phone?: string | null;\n job_title?: string | null;\n job_department?: string | null;\n seniority_level?: string | null;\n role?: string | null;\n linkedin_url?: string | null;\n linkedin_headline?: string | null;\n city?: string | null;\n state?: string | null;\n country?: string | null;\n company_name?: string | null;\n company_domain?: string | null;\n company_industry?: string | null;\n company_employee_count?: string | null;\n company_country?: string | null;\n confidence_score?: number | null;\n}\n\nexport interface SearchCompanyItem {\n name?: string | null;\n domain?: string | null;\n website?: string | null;\n description?: string | null;\n industry?: string | null;\n industry_group?: string | null;\n employee_count?: string | null;\n revenue?: string | null;\n founded_year?: number | null;\n phone?: string | null;\n address?: string | null;\n city?: string | null;\n state?: string | null;\n country?: string | null;\n zip?: number | null;\n linkedin_url?: string | null;\n linkedin_followers?: string | null;\n facebook_url?: string | null;\n twitter_url?: string | null;\n crunchbase_url?: string | null;\n logo_url?: string | null;\n}\n\nexport interface SearchSaveResult {\n list_id: number;\n list_title: string;\n estimated_total: number;\n status: string;\n}\n\n/**\n * Search API — prospect the open-data graph for new contacts and companies by\n * filter, and optionally save the matches straight into a list. Requires API\n * key (server-side). Built on the hardened HTTP core, so every method throws a\n * typed `G8Error` on failure and retries transient errors.\n *\n * Backed by `/api/v1/search`.\n */\nexport const createSearchClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n const body = (p: SearchParams) => ({ filters: [], page: 1, limit: 25, ...p });\n\n return {\n /** Search open-data contacts by filter. */\n async contacts(params: SearchParams = {}): Promise<{ data: SearchContactItem[] }> {\n return request(baseUrl, \"/api/v1/search/contacts\", apiKey, { method: \"POST\", body: body(params) });\n },\n\n /** Search open-data companies by filter. */\n async companies(params: SearchParams = {}): Promise<{ data: SearchCompanyItem[] }> {\n return request(baseUrl, \"/api/v1/search/companies\", apiKey, { method: \"POST\", body: body(params) });\n },\n\n /** Search contacts and save the matches into a new list. */\n async saveContacts(params: SearchSaveParams): Promise<SearchSaveResult> {\n const resp = await request<{ data?: SearchSaveResult }>(baseUrl, \"/api/v1/search/contacts/save\", apiKey, {\n method: \"POST\",\n body: { filters: [], page: 1, limit: 25, max_results: 1000, ...params },\n });\n return resp.data ?? (resp as unknown as SearchSaveResult);\n },\n\n /** Search companies and save the matches into a new list. */\n async saveCompanies(params: SearchSaveParams): Promise<SearchSaveResult> {\n const resp = await request<{ data?: SearchSaveResult }>(baseUrl, \"/api/v1/search/companies/save\", apiKey, {\n method: \"POST\",\n body: { filters: [], page: 1, limit: 25, max_results: 1000, ...params },\n });\n return resp.data ?? (resp as unknown as SearchSaveResult);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface AgencyInfo {\n agency_org_id: string;\n agency_org_name: string | null;\n is_agency: boolean;\n client_count: number;\n /** Request header to set when operating a client org (e.g. \"X-Target-Org-Id\"). */\n target_header: string;\n}\n\nexport interface AgencyClient {\n /** Pass this as the `X-Target-Org-Id` header to operate this client org. */\n org_id: string;\n}\n\n/**\n * Agency API — for agency-scoped API keys (minted with `is_agency: true`).\n * Discover the agency credential and the client orgs it may operate. To act on a\n * client org, set the `X-Target-Org-Id` header (see `target_header`) to that\n * client's `org_id` on your subsequent requests. Requires an agency API key\n * (server-side); a non-agency key gets a `403`.\n *\n * Built on the hardened HTTP core (typed `G8Error` + retries). Backed by\n * `/api/v1/agency`.\n */\nexport const createAgencyClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** Describe the agency credential: agency org + authorized client count. */\n async me(): Promise<AgencyInfo> {\n const resp = await request<{ data?: AgencyInfo }>(baseUrl, \"/api/v1/agency/me\", apiKey);\n return resp.data ?? (resp as unknown as AgencyInfo);\n },\n\n /** List the client orgs this agency key may target via `X-Target-Org-Id`. */\n async clients(): Promise<{ data: AgencyClient[] }> {\n return request(baseUrl, \"/api/v1/agency/clients\", apiKey);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface MarketplaceProfile {\n id: string;\n email: string;\n first_name?: string | null;\n last_name?: string | null;\n marketplace_role?: string | null;\n country_code?: string | null;\n monthly_rate_usd?: string | null;\n per_meeting_rate_usd?: string | null;\n availability_status?: string | null;\n bio?: string | null;\n is_complete: boolean;\n}\n\nexport interface MarketplaceOffer {\n id: string;\n org_id: string;\n org_name?: string | null;\n sdr_id: string;\n status: string;\n monthly_rate_usd?: string | null;\n per_meeting_rate_usd?: string | null;\n created_at?: string | null;\n}\n\nexport interface MarketplaceHiring {\n id: string;\n org_id: string;\n sdr_id: string;\n status: string;\n sdr_name?: string | null;\n sdr_role?: string | null;\n sdr_email?: string | null;\n monthly_rate_usd?: string | null;\n per_meeting_rate_usd?: string | null;\n started_at?: string | null;\n}\n\n/**\n * Marketplace API — for SDR/AE talent on the graph8 marketplace. View your\n * profile, see pending hire offers and respond to them, and list your active\n * hirings. Requires a personal API key (server-side). Built on the hardened\n * HTTP core, so every method throws a typed `G8Error` on failure and retries\n * transient errors.\n *\n * Backed by `/api/v1/marketplace`.\n */\nexport const createMarketplaceClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n const base = \"/api/v1/marketplace\";\n\n return {\n /** Your own marketplace SDR profile. */\n async profile(): Promise<MarketplaceProfile> {\n const resp = await request<{ data?: MarketplaceProfile }>(baseUrl, `${base}/me/profile`, apiKey);\n return resp.data ?? (resp as unknown as MarketplaceProfile);\n },\n\n /** Pending hire offers you can accept or reject. */\n async offers(): Promise<{ offers: MarketplaceOffer[]; count: number }> {\n const resp = await request<{ data?: { offers: MarketplaceOffer[]; count: number } }>(\n baseUrl,\n `${base}/me/offers`,\n apiKey,\n );\n return resp.data ?? (resp as unknown as { offers: MarketplaceOffer[]; count: number });\n },\n\n /** Accept a pending hire offer (by hiring id). */\n async acceptOffer(hiringId: string): Promise<Record<string, unknown>> {\n const resp = await request<{ data?: Record<string, unknown> }>(\n baseUrl,\n `${base}/me/offers/${hiringId}/accept`,\n apiKey,\n { method: \"POST\" },\n );\n return resp.data ?? (resp as unknown as Record<string, unknown>);\n },\n\n /** Reject a pending hire offer (by hiring id). */\n async rejectOffer(hiringId: string): Promise<Record<string, unknown>> {\n const resp = await request<{ data?: Record<string, unknown> }>(\n baseUrl,\n `${base}/me/offers/${hiringId}/reject`,\n apiKey,\n { method: \"POST\" },\n );\n return resp.data ?? (resp as unknown as Record<string, unknown>);\n },\n\n /** Your active hiring contracts. */\n async hirings(): Promise<{ hirings: MarketplaceHiring[]; count: number }> {\n const resp = await request<{ data?: { hirings: MarketplaceHiring[]; count: number } }>(\n baseUrl,\n `${base}/me/hirings`,\n apiKey,\n );\n return resp.data ?? (resp as unknown as { hirings: MarketplaceHiring[]; count: number });\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface Snippet {\n write_key: string;\n tracking_host: string;\n domains: string[];\n /** Ready-to-use React component import for @graph8/nextjs. */\n react_snippet: string;\n /** Vanilla JS script tag for non-React apps. */\n script_tag: string;\n /** Full configuration object (gtm/config.json). */\n config: Record<string, unknown>;\n}\n\n/**\n * Snippet API — fetch your org's graph8 tracking snippet programmatically, to\n * embed the tracker into an app or a customer's site (the write key, a React\n * component, a vanilla `<script>` tag, allowed domains, and the full config).\n * Requires an API key (server-side). Built on the hardened HTTP core, so it\n * throws a typed `G8Error` on failure and retries transient errors.\n *\n * Backed by `GET /api/v1/snippet`.\n */\nexport const createSnippetClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** Get your org's tracking snippet (write key + React/script-tag embeds + config). */\n async get(): Promise<Snippet> {\n const resp = await request<{ data?: Snippet }>(baseUrl, \"/api/v1/snippet\", apiKey);\n return resp.data ?? (resp as unknown as Snippet);\n },\n };\n};\n"],"mappings":"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","names":["DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","request","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","module"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/core.ts","../src/forms.ts","../src/utils.ts","../src/visitors.ts","../src/copilot.ts","../src/chat.ts","../src/calendar.ts","../src/http.ts","../src/enrich.ts","../src/sequences.ts","../src/campaigns.ts","../src/signals.ts","../src/voice.ts","../src/webhooks.ts","../src/contacts.ts","../src/companies.ts","../src/lists.ts","../src/notes.ts","../src/tasks.ts","../src/fields.ts","../src/deals.ts","../src/inbox.ts","../src/quotes.ts","../src/pipelines.ts","../src/workflows.ts","../src/skills.ts","../src/intent.ts","../src/studio.ts","../src/meetings.ts","../src/audiences.ts","../src/search.ts","../src/agency.ts","../src/marketplace.ts","../src/snippet.ts"],"sourcesContent":["export { g8 } from \"./core\";\n\n// HTTP core (B2): typed errors, automatic retries, idempotency, auto-pagination.\nexport { G8Error, request, paginate, isRetryableStatus, parseRetryAfter, backoffDelayMs } from \"./http\";\nexport type { RequestOptions, PaginatedResponse } from \"./http\";\n\n// Core types\nexport type { G8Config, G8PrivacyConfig, TrackProperties, IdentifyProperties, EnrichLookupResult } from \"./types\";\n\n// Module types\nexport type { VisitorCompany, VisitorScore } from \"./visitors\";\nexport type { CopilotConfig } from \"./copilot\";\nexport type { ChatConfig } from \"./chat\";\nexport type { CalendarConfig, TimeSlot, Booking, BookingRequest } from \"./calendar\";\nexport type { PersonEnrichment, CompanyEnrichment, EmailVerification, SearchFilter, SearchResults } from \"./enrich\";\nexport type {\n Sequence,\n AddToSequenceConfig,\n SequenceListItem,\n SequenceListParams,\n SequenceDetail,\n SequenceContactItem,\n SequenceContactsParams,\n SequenceActionResult,\n SequenceKind,\n SequenceStepType,\n SequenceStepInputType,\n SequenceStepConfig,\n SequenceChannelConfig,\n SequenceCreateParams,\n SequenceCreateResult,\n SequenceUpdateParams,\n SequenceStepUpdateParams,\n SequencePreviewStep,\n SequencePreviewChannel,\n SequencePreview,\n SequenceAnalytics,\n} from \"./sequences\";\nexport type {\n InboxChannel,\n InboxContact,\n InboxTag,\n InboxAssignee,\n InboxMessage,\n InboxThread,\n InboxListParams,\n InboxAssignResult,\n InboxTagResult,\n InboxDraft,\n InboxSendParams,\n InboxSendResult,\n} from \"./inbox\";\nexport type {\n Campaign,\n CampaignCreateConfig,\n CampaignLaunchExecution,\n CampaignLaunchResult,\n} from \"./campaigns\";\nexport type { IntentSignals } from \"./signals\";\nexport type {\n VoicePagination,\n DialerSessionSummary,\n DialerSessionsListResult,\n DialerSessionsListParams,\n DialerStatsParams,\n DialerReportFilters,\n DialerReportMetric,\n DialerStatsResult,\n DialerNumberInfo,\n DialerNumbersListResult,\n MissedCallback,\n MissedCallbacksResult,\n CallGradingResult,\n DialerAgentSummary,\n DialerAgentsListResult,\n DialerAgentsListParams,\n DialerSessionCreateParams,\n DialerSessionCreateResult,\n DialerSessionStatus,\n DialerSessionStatusUpdateResult,\n DialerSessionResumeResult,\n} from \"./voice\";\nexport type { WebhookEvent, WebhookEventPayload, ConstructEventOptions } from \"./webhooks\";\nexport { constructEvent, WebhookSignatureError, KNOWN_WEBHOOK_EVENTS } from \"./webhooks\";\nexport type {\n Contact,\n ContactListParams,\n ContactCreateParams,\n ContactUpdateParams,\n ContactColumn,\n ContactColumnCreateParams,\n} from \"./contacts\";\nexport type {\n Company,\n CompanyListParams,\n CompanyUpdateParams,\n CompanyContact,\n CompanyColumn,\n CompanyColumnCreateParams,\n} from \"./companies\";\nexport type { ContactList, ListContact } from \"./lists\";\nexport type { Note } from \"./notes\";\nexport type { Task, TaskCreateParams, TaskUpdateParams, TaskListParams } from \"./tasks\";\nexport type {\n Field,\n CreatedField,\n FieldCreateParams,\n FieldDeleteParams,\n SetFieldValueParams,\n} from \"./fields\";\nexport type {\n Deal,\n DealCreateParams,\n DealUpdateParams,\n DealListParams,\n Pipeline,\n PipelineStage,\n ContactDeal,\n PaginationMeta,\n} from \"./deals\";\nexport type {\n QuoteSummary,\n QuoteDetail,\n QuoteLineItem,\n QuoteStatus,\n QuoteCreateParams,\n QuoteUpdateParams,\n QuoteSendParams,\n QuoteListParams,\n QuotableProduct,\n QuoteSettings,\n} from \"./quotes\";\nexport type {\n StagePipeline,\n StagePipelineStage,\n StagePipelineCreateParams,\n StagePipelineUpdateParams,\n StageCreateParams,\n StageUpdateParams,\n EvidenceKey,\n PipelineSuggestion,\n} from \"./pipelines\";\nexport type {\n Workflow,\n WorkflowNode,\n WorkflowConnection,\n WorkflowConfig,\n WorkflowCreateParams,\n WorkflowUpdateParams,\n WorkflowExecution,\n WorkflowListParams,\n NodeTypeSchema,\n} from \"./workflows\";\nexport type {\n Skill,\n SkillType,\n SkillInputField,\n SkillCreateLLMParams,\n SkillCreateAPIParams,\n SkillUpdateLLMParams,\n SkillUpdateAPIParams,\n SkillTemplate,\n SkillListParams,\n} from \"./skills\";\nexport type {\n IntentKeyword,\n IntentPage,\n IntentVisitor,\n IntentCompany,\n IntentContact,\n IntentStats,\n} from \"./intent\";\nexport type {\n GlobalContextDocument,\n Persona,\n ICP,\n IntelligenceData,\n ResearchReport,\n} from \"./studio\";\nexport type {\n MeetingSummary,\n MeetingDetail,\n MeetingAttendee,\n MeetingTranscriptLine,\n MeetingAnalysis,\n MeetingListParams,\n} from \"./meetings\";\nexport type {\n AudienceSync,\n AudienceSyncPlatform,\n AudienceSyncMode,\n AudienceSyncCreateParams,\n AudienceSyncUpdateParams,\n AudienceSyncRun,\n AudienceSyncError,\n} from \"./audiences\";\nexport type {\n SearchOperator,\n SearchCondition,\n SearchParams,\n SearchSaveParams,\n SearchContactItem,\n SearchCompanyItem,\n SearchSaveResult,\n} from \"./search\";\nexport type { AgencyInfo, AgencyClient } from \"./agency\";\nexport type { MarketplaceProfile, MarketplaceOffer, MarketplaceHiring } from \"./marketplace\";\nexport type { Snippet } from \"./snippet\";\n","import { jitsuAnalytics } from \"@jitsu/js\";\nimport type { AnalyticsInterface } from \"@jitsu/js\";\nimport type { G8Config, TrackProperties, IdentifyProperties } from \"./types\";\nimport { createFormsClient } from \"./forms\";\nimport { createVisitorsClient } from \"./visitors\";\nimport { createCopilotClient } from \"./copilot\";\nimport { createChatClient } from \"./chat\";\nimport { createCalendarClient } from \"./calendar\";\nimport { createEnrichClient } from \"./enrich\";\nimport { createSequencesClient } from \"./sequences\";\nimport { createCampaignsClient } from \"./campaigns\";\nimport { createSignalsClient } from \"./signals\";\nimport { createVoiceClient } from \"./voice\";\nimport { createWebhooksClient } from \"./webhooks\";\nimport { createContactsClient } from \"./contacts\";\nimport { createCompaniesClient } from \"./companies\";\nimport { createListsClient } from \"./lists\";\nimport { createNotesClient } from \"./notes\";\nimport { createTasksClient } from \"./tasks\";\nimport { createFieldsClient } from \"./fields\";\nimport { createDealsClient } from \"./deals\";\nimport { createInboxClient } from \"./inbox\";\nimport { createQuotesClient } from \"./quotes\";\nimport { createPipelinesClient } from \"./pipelines\";\nimport { createWorkflowsClient } from \"./workflows\";\nimport { createSkillsClient } from \"./skills\";\nimport { createIntentClient } from \"./intent\";\nimport { createStudioClient } from \"./studio\";\nimport { createMeetingsClient } from \"./meetings\";\nimport { createAudiencesClient } from \"./audiences\";\nimport { createSearchClient } from \"./search\";\nimport { createAgencyClient } from \"./agency\";\nimport { createMarketplaceClient } from \"./marketplace\";\nimport { createSnippetClient } from \"./snippet\";\nimport { isServer } from \"./utils\";\n\nconst DEFAULT_HOST = \"https://t.graph8.com\";\nconst DEFAULT_API = \"https://be.graph8.com\";\n\n/**\n * graph8 SDK client.\n *\n * Handles event tracking, identity, and progressive forms.\n *\n * Usage:\n * import { g8 } from '@graph8/sdk';\n * g8.init({ writeKey: 'your_write_key' });\n * g8.track('page_view', { page: '/pricing' });\n * g8.identify('user@acme.com', { name: 'John', company: 'Acme' });\n */\nclass G8 {\n /** @internal */ client: AnalyticsInterface | null = null;\n /** @internal */ config: G8Config | null = null;\n /** @internal */ _forms: ReturnType<typeof createFormsClient> | null = null;\n /** @internal */ _visitors: ReturnType<typeof createVisitorsClient> | null = null;\n /** @internal */ _copilot: ReturnType<typeof createCopilotClient> | null = null;\n /** @internal */ _chat: ReturnType<typeof createChatClient> | null = null;\n /** @internal */ _calendar: ReturnType<typeof createCalendarClient> | null = null;\n /** @internal */ _enrich: ReturnType<typeof createEnrichClient> | null = null;\n /** @internal */ _sequences: ReturnType<typeof createSequencesClient> | null = null;\n /** @internal */ _campaigns: ReturnType<typeof createCampaignsClient> | null = null;\n /** @internal */ _signals: ReturnType<typeof createSignalsClient> | null = null;\n /** @internal */ _voice: ReturnType<typeof createVoiceClient> | null = null;\n /** @internal */ _webhooks: ReturnType<typeof createWebhooksClient> | null = null;\n /** @internal */ _contacts: ReturnType<typeof createContactsClient> | null = null;\n /** @internal */ _companies: ReturnType<typeof createCompaniesClient> | null = null;\n /** @internal */ _lists: ReturnType<typeof createListsClient> | null = null;\n /** @internal */ _notes: ReturnType<typeof createNotesClient> | null = null;\n /** @internal */ _tasks: ReturnType<typeof createTasksClient> | null = null;\n /** @internal */ _fields: ReturnType<typeof createFieldsClient> | null = null;\n /** @internal */ _deals: ReturnType<typeof createDealsClient> | null = null;\n /** @internal */ _inbox: ReturnType<typeof createInboxClient> | null = null;\n /** @internal */ _quotes: ReturnType<typeof createQuotesClient> | null = null;\n /** @internal */ _pipelines: ReturnType<typeof createPipelinesClient> | null = null;\n /** @internal */ _workflows: ReturnType<typeof createWorkflowsClient> | null = null;\n /** @internal */ _skills: ReturnType<typeof createSkillsClient> | null = null;\n /** @internal */ _intent: ReturnType<typeof createIntentClient> | null = null;\n /** @internal */ _studio: ReturnType<typeof createStudioClient> | null = null;\n /** @internal */ _meetings: ReturnType<typeof createMeetingsClient> | null = null;\n /** @internal */ _audiences: ReturnType<typeof createAudiencesClient> | null = null;\n /** @internal */ _search: ReturnType<typeof createSearchClient> | null = null;\n /** @internal */ _agency: ReturnType<typeof createAgencyClient> | null = null;\n /** @internal */ _marketplace: ReturnType<typeof createMarketplaceClient> | null = null;\n /** @internal */ _snippet: ReturnType<typeof createSnippetClient> | null = null;\n\n /**\n * Initialize the graph8 SDK. Must be called before any other method.\n * Safe to call on the server (SSR) - becomes a no-op for tracking.\n */\n init(config: G8Config): void {\n this.config = config;\n\n if (!isServer) {\n this.client = jitsuAnalytics({\n host: config.host || DEFAULT_HOST,\n writeKey: config.writeKey || \"\",\n debug: config.debug,\n });\n }\n\n const apiUrl = config.apiUrl || DEFAULT_API;\n const writeKey = config.writeKey || \"\";\n const apiKey = config.apiKey || \"\";\n\n // Public (write key) clients\n if (writeKey) {\n this._forms = createFormsClient(writeKey, apiUrl);\n this._visitors = createVisitorsClient(writeKey, apiUrl);\n this._copilot = createCopilotClient(writeKey, apiUrl);\n this._chat = createChatClient(writeKey, apiUrl);\n this._calendar = createCalendarClient(apiUrl);\n this._signals = createSignalsClient(writeKey, false, apiUrl);\n }\n\n // Private (API key) clients\n if (apiKey) {\n this._enrich = createEnrichClient(apiKey, apiUrl);\n this._sequences = createSequencesClient(apiKey, apiUrl);\n this._campaigns = createCampaignsClient(apiKey, apiUrl);\n this._voice = createVoiceClient(apiKey, apiUrl);\n this._webhooks = createWebhooksClient(apiKey, apiUrl);\n this._contacts = createContactsClient(apiKey, apiUrl);\n this._companies = createCompaniesClient(apiKey, apiUrl);\n this._lists = createListsClient(apiKey, apiUrl);\n this._notes = createNotesClient(apiKey, apiUrl);\n this._tasks = createTasksClient(apiKey, apiUrl);\n this._fields = createFieldsClient(apiKey, apiUrl);\n this._deals = createDealsClient(apiKey, apiUrl);\n this._inbox = createInboxClient(apiKey, apiUrl);\n this._quotes = createQuotesClient(apiKey, apiUrl);\n this._pipelines = createPipelinesClient(apiKey, apiUrl);\n this._workflows = createWorkflowsClient(apiKey, apiUrl);\n this._skills = createSkillsClient(apiKey, apiUrl);\n this._intent = createIntentClient(apiKey, apiUrl);\n this._studio = createStudioClient(apiKey, apiUrl);\n this._meetings = createMeetingsClient(apiKey, apiUrl);\n this._audiences = createAudiencesClient(apiKey, apiUrl);\n this._search = createSearchClient(apiKey, apiUrl);\n this._agency = createAgencyClient(apiKey, apiUrl);\n this._marketplace = createMarketplaceClient(apiKey, apiUrl);\n this._snippet = createSnippetClient(apiKey, apiUrl);\n // Override signals with API key version for full access\n this._signals = createSignalsClient(apiKey, true, apiUrl);\n }\n }\n\n // -- Core tracking (via Jitsu) --\n\n /** Track a custom event. */\n track(event: string, properties?: TrackProperties): void { this.client?.track(event, properties); }\n\n /** Identify a user with properties. */\n identify(userId: string, properties?: IdentifyProperties): void { this.client?.identify(userId, properties); }\n\n /** Track a page view. */\n page(properties?: TrackProperties): void { this.client?.page(properties); }\n\n /** Clear user identity (on logout). */\n reset(): void { this.client?.reset(); }\n\n // -- Module accessors --\n\n /** Progressive form helpers. */\n get forms() { this._assertInit(); return this._forms!; }\n\n /** Visitor intelligence - IP to company, engagement scoring. */\n get visitors() { this._assertInit(); return this._visitors!; }\n\n /** AI copilot widget. */\n get copilot() { this._assertInit(); return this._copilot!; }\n\n /** Webchat widget. */\n get chat() { this._assertInit(); return this._chat!; }\n\n /** Calendar and booking. */\n get calendar() { this._assertInit(); return this._calendar!; }\n\n /** Enrichment API (requires API key). */\n get enrich() { this._assertKey(\"enrich\"); return this._enrich!; }\n\n /** Sequences (requires API key). */\n get sequences() { this._assertKey(\"sequences\"); return this._sequences!; }\n\n /** Campaigns (requires API key). */\n get campaigns() { this._assertKey(\"campaigns\"); return this._campaigns!; }\n\n /** Intent signals. */\n get signals() { this._assertInit(); return this._signals!; }\n\n /** Voice AI (requires API key). */\n get voice() { this._assertKey(\"voice\"); return this._voice!; }\n\n /** Webhook event listeners (requires API key). */\n get webhooks() { this._assertKey(\"webhooks\"); return this._webhooks!; }\n\n /** Contacts CRUD (requires API key). */\n get contacts() { this._assertKey(\"contacts\"); return this._contacts!; }\n\n /** Companies CRUD (requires API key). */\n get companies() { this._assertKey(\"companies\"); return this._companies!; }\n\n /** Lists management (requires API key). */\n get lists() { this._assertKey(\"lists\"); return this._lists!; }\n\n /** Notes on contacts (requires API key). */\n get notes() { this._assertKey(\"notes\"); return this._notes!; }\n\n /** Tasks on contacts (requires API key). */\n get tasks() { this._assertKey(\"tasks\"); return this._tasks!; }\n\n /** Custom fields management (requires API key). */\n get fields() { this._assertKey(\"fields\"); return this._fields!; }\n\n /** Deals and pipelines (requires API key). */\n get deals() { this._assertKey(\"deals\"); return this._deals!; }\n\n /** Multi-channel inbox — read + reply across email, SMS, LinkedIn (requires API key). */\n get inbox() { this._assertKey(\"inbox\"); return this._inbox!; }\n\n /** Quote-to-cash: draft, send, sign, payment-link quotes (requires API key). */\n get quotes() { this._assertKey(\"quotes\"); return this._quotes!; }\n\n /** Stage Checklist v2 pipelines: workflow stages with evidence + scripts (requires API key). */\n get pipelines() { this._assertKey(\"pipelines\"); return this._pipelines!; }\n\n /** Workflow builder — multi-node automation graphs with execution lifecycle (requires API key). */\n get workflows() { this._assertKey(\"workflows\"); return this._workflows!; }\n\n /** Skill authoring — LLM and API building blocks that workflows compose (requires API key). */\n get skills() { this._assertKey(\"skills\"); return this._skills!; }\n\n /** Intent tracking — keyword groups, page visitors, account-level intent (requires API key). */\n get intent() { this._assertKey(\"intent\"); return this._intent!; }\n\n /** Studio context — ICPs, personas, brand briefs, intelligence, AI research reports (requires API key). */\n get studio() { this._assertKey(\"studio\"); return this._studio!; }\n\n /** Meetings — read scheduled, completed, cancelled meetings with transcripts + AI analysis (requires API key). */\n get meetings() { this._assertKey(\"meetings\"); return this._meetings!; }\n\n /** Audiences — sync audience lists to ad platforms (Meta, LinkedIn, Google, X) (requires API key). */\n get audiences() { this._assertKey(\"audiences\"); return this._audiences!; }\n\n /** Search — prospect open-data contacts + companies by filter, optionally save to a list (requires API key). */\n get search() { this._assertKey(\"search\"); return this._search!; }\n\n /** Agency — for agency keys: discover the agency credential + the client orgs it may target (requires API key). */\n get agency() { this._assertKey(\"agency\"); return this._agency!; }\n\n /** Marketplace — for SDR/AE talent: profile, hire offers (accept/reject), active hirings (requires API key). */\n get marketplace() { this._assertKey(\"marketplace\"); return this._marketplace!; }\n\n /** Snippet — fetch your org's tracking snippet (write key + React/script-tag embeds + config) for embedding (requires API key). */\n get snippet() { this._assertKey(\"snippet\"); return this._snippet!; }\n\n /** Whether the SDK has been initialized. */\n get initialized(): boolean { return this.config !== null; }\n\n /** @internal */\n _assertInit(): void {\n if (!this.config) throw new Error(\"g8.init() must be called first\");\n }\n\n /** @internal */\n _assertKey(module: string): void {\n this._assertInit();\n if (!this.config!.apiKey) throw new Error(`g8.${module} requires an API key. Use g8.init({ apiKey: '...' })`);\n }\n}\n\n/** Singleton g8 client instance. */\nexport const g8 = new G8();\n","import type { EnrichLookupResult } from \"./types\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\n/**\n * Progressive form enrichment - checks what fields graph8 already knows\n * about a contact so your form can skip those fields.\n *\n * Calls POST /api/v1/public/enrich/lookup (authenticated via write key).\n */\nexport const createFormsClient = (writeKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /**\n * Look up known fields for an email address.\n *\n * Use this in progressive forms: after the user enters their email,\n * check what graph8 already knows and only show missing fields.\n */\n async lookup(email: string): Promise<EnrichLookupResult> {\n const resp = await fetch(`${baseUrl}/api/v1/public/enrich/lookup`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Write-Key\": writeKey,\n },\n body: JSON.stringify({ email }),\n });\n\n if (!resp.ok) {\n return { found: false, known_fields: {}, missing_fields: [] };\n }\n\n const data = await resp.json();\n return data.data || data;\n },\n };\n};\n","/** Check if running on the server (SSR). */\nexport const isServer = typeof window === \"undefined\";\n\n/** Safely get the window object (returns undefined on server). */\nexport const getWindow = (): Window | undefined =>\n isServer ? undefined : window;\n\n/**\n * Derive the APP origin (which serves the embed pages) from the API origin.\n *\n * `apiUrl` addresses the FastAPI backend — `be.graph8.com` in production — and\n * that host does not serve any page routes: `/webchat/embed` and\n * `/copilot/embed` are Next.js pages on `app.graph8.com`. The two hosts are\n * disjoint, so a single base URL cannot address both; an iframe pointed at\n * `${apiUrl}/webchat/embed` renders the backend's `{\"detail\":\"Not Found\"}`.\n *\n * This is the inverse of `detectApiBaseUrl` in\n * `frontend/chat-script/src/config.ts`, which maps `app.` → `be.` to find the\n * API from the page. Same host convention, read the other way.\n *\n * Anything that is not a recognised graph8 or localhost origin is returned\n * unchanged, so a self-hosted deployment keeps serving both from one host.\n */\nexport const resolveAppBaseUrl = (apiBaseUrl: string): string => {\n try {\n const url = new URL(apiBaseUrl);\n if (url.hostname === \"localhost\" || url.hostname === \"127.0.0.1\") {\n // Backend dev ports (8000 http / 8011 https) → Next dev server on 3000.\n url.port = \"3000\";\n return url.origin;\n }\n if (url.hostname.endsWith(\"graph8.com\")) {\n url.hostname = url.hostname.replace(/^be\\./, \"app.\");\n return url.origin;\n }\n } catch {\n // Not a parseable URL — leave the caller's value alone.\n }\n return apiBaseUrl;\n};\n","import type { G8Config } from \"./types\";\nimport { isServer } from \"./utils\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface VisitorCompany {\n company_name: string | null;\n company_domain: string | null;\n industry: string | null;\n employee_count: string | null;\n city: string | null;\n country: string | null;\n confidence: number;\n}\n\nexport interface VisitorScore {\n engagement: number;\n intent: \"low\" | \"medium\" | \"high\";\n signals: string[];\n}\n\ntype IntentCallback = (visitor: VisitorCompany & VisitorScore) => void;\n\n/**\n * Visitor intelligence - identify anonymous visitors by IP → company.\n *\n * Requires write key auth. Works client-side only.\n */\nexport const createVisitorsClient = (writeKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n let intentInterval: ReturnType<typeof setInterval> | null = null;\n\n const headers = () => ({\n \"Content-Type\": \"application/json\",\n \"X-Write-Key\": writeKey,\n });\n\n return {\n /** Identify the current visitor's company from their IP address. */\n async identify(): Promise<VisitorCompany> {\n if (isServer) return { company_name: null, company_domain: null, industry: null, employee_count: null, city: null, country: null, confidence: 0 };\n\n const resp = await fetch(`${baseUrl}/api/v1/public/visitors/company`, { headers: headers() });\n if (!resp.ok) return { company_name: null, company_domain: null, industry: null, employee_count: null, city: null, country: null, confidence: 0 };\n const data = await resp.json();\n return data.data || data;\n },\n\n /** Get engagement score for the current visitor. */\n async score(): Promise<VisitorScore> {\n if (isServer) return { engagement: 0, intent: \"low\", signals: [] };\n\n const resp = await fetch(`${baseUrl}/api/v1/public/visitors/score`, { headers: headers() });\n if (!resp.ok) return { engagement: 0, intent: \"low\", signals: [] };\n const data = await resp.json();\n return data.data || data;\n },\n\n /** Listen for visitors matching an intent level. Polls every 30 seconds. */\n onIntent(level: \"low\" | \"medium\" | \"high\", callback: IntentCallback): () => void {\n if (isServer) return () => {};\n\n const check = async () => {\n try {\n const [company, scoreData] = await Promise.all([\n this.identify(),\n this.score(),\n ]);\n if (scoreData.intent === level || (level === \"medium\" && scoreData.intent === \"high\")) {\n callback({ ...company, ...scoreData });\n }\n } catch { /* silent */ }\n };\n\n check();\n intentInterval = setInterval(check, 30_000);\n\n return () => {\n if (intentInterval) clearInterval(intentInterval);\n };\n },\n };\n};\n","import { isServer } from \"./utils\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface CopilotConfig {\n /** Initial greeting message */\n greeting?: string;\n /** Context passed to the AI */\n context?: Record<string, unknown>;\n /** Widget position */\n position?: \"bottom-right\" | \"bottom-left\";\n /** Widget theme */\n theme?: \"light\" | \"dark\" | \"auto\";\n}\n\ntype CopilotEvent = \"message\" | \"tool_used\" | \"open\" | \"close\" | \"error\";\ntype CopilotCallback = (data: Record<string, unknown>) => void;\ntype ActionHandler = (params: Record<string, unknown>) => void | Promise<void>;\n\n/**\n * Copilot - embeddable AI assistant with org knowledge base access.\n *\n * Client-side (write key) for the widget embed.\n */\nexport const createCopilotClient = (writeKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n const listeners: Map<CopilotEvent, CopilotCallback[]> = new Map();\n const actions: Map<string, ActionHandler> = new Map();\n let widgetEl: HTMLElement | null = null;\n\n const emit = (event: CopilotEvent, data: Record<string, unknown> = {}) => {\n listeners.get(event)?.forEach((cb) => cb(data));\n };\n\n return {\n /** Open the copilot widget. */\n open(config?: CopilotConfig): void {\n if (isServer) return;\n\n // Remove existing widget if any\n if (widgetEl) widgetEl.remove();\n\n const position = config?.position || \"bottom-right\";\n const posStyle = position === \"bottom-left\" ? \"left:16px;\" : \"right:16px;\";\n\n const iframe = document.createElement(\"iframe\");\n iframe.src = `${baseUrl}/copilot/embed?write_key=${writeKey}&theme=${config?.theme || \"auto\"}`;\n iframe.style.cssText = `position:fixed;bottom:16px;${posStyle}width:400px;height:600px;border:none;border-radius:12px;box-shadow:0 8px 32px rgba(0,0,0,0.15);z-index:99998;`;\n iframe.id = \"g8-copilot-widget\";\n\n document.body.appendChild(iframe);\n widgetEl = iframe;\n emit(\"open\");\n },\n\n /** Send a message to the copilot programmatically. */\n async ask(message: string): Promise<string> {\n const resp = await fetch(`${baseUrl}/api/v1/public/copilot/chat`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", \"X-Write-Key\": writeKey },\n body: JSON.stringify({ message }),\n });\n if (!resp.ok) return \"Sorry, I could not process that request.\";\n const data = await resp.json();\n return data.response || data.data?.response || \"\";\n },\n\n /** Register a custom action the copilot can trigger. */\n registerAction(name: string, handler: ActionHandler): void {\n actions.set(name, handler);\n },\n\n /** Listen for copilot events. */\n on(event: CopilotEvent, callback: CopilotCallback): void {\n if (!listeners.has(event)) listeners.set(event, []);\n listeners.get(event)!.push(callback);\n },\n\n /** Close the copilot widget. */\n close(): void {\n if (widgetEl) {\n widgetEl.remove();\n widgetEl = null;\n emit(\"close\");\n }\n },\n };\n};\n","import { isServer, resolveAppBaseUrl } from \"./utils\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface ChatConfig {\n /** Agent ID to connect to */\n agentId?: string;\n /** Pre-filled first message */\n message?: string;\n /** Widget position */\n position?: \"bottom-right\" | \"bottom-left\";\n /** Widget theme */\n theme?: \"light\" | \"dark\" | \"auto\";\n /** Custom greeting */\n greeting?: string;\n /** Custom avatar URL */\n avatar?: string;\n}\n\ntype ChatEvent = \"message\" | \"human_transfer\" | \"open\" | \"close\" | \"error\";\ntype ChatCallback = (data: Record<string, unknown>) => void;\n\n/**\n * Webchat - live chat + AI chat embedded in any app.\n *\n * Uses WebSocket connection to the voice/chat agent backend.\n * Public - no API key needed (org/agent IDs are in the config).\n */\nexport const createChatClient = (writeKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n // The embed page is a Next.js route on the APP host, not the API host.\n const appUrl = resolveAppBaseUrl(baseUrl);\n const listeners: Map<ChatEvent, ChatCallback[]> = new Map();\n let widgetEl: HTMLElement | null = null;\n let ws: WebSocket | null = null;\n\n const emit = (event: ChatEvent, data: Record<string, unknown> = {}) => {\n listeners.get(event)?.forEach((cb) => cb(data));\n };\n\n return {\n /** Open the chat widget. */\n open(config?: ChatConfig): void {\n if (isServer) return;\n\n if (widgetEl) widgetEl.remove();\n\n const position = config?.position || \"bottom-right\";\n const posStyle = position === \"bottom-left\" ? \"left:16px;\" : \"right:16px;\";\n\n const iframe = document.createElement(\"iframe\");\n iframe.src = `${appUrl}/webchat/embed?write_key=${writeKey}&theme=${config?.theme || \"auto\"}`;\n iframe.style.cssText = `position:fixed;bottom:16px;${posStyle}width:380px;height:560px;border:none;border-radius:12px;box-shadow:0 8px 32px rgba(0,0,0,0.15);z-index:99997;`;\n iframe.id = \"g8-chat-widget\";\n\n document.body.appendChild(iframe);\n widgetEl = iframe;\n emit(\"open\");\n },\n\n /** Send a message. */\n send(message: string): void {\n if (ws && ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: \"message\", content: message }));\n }\n },\n\n /** Listen for chat events. */\n on(event: ChatEvent, callback: ChatCallback): void {\n if (!listeners.has(event)) listeners.set(event, []);\n listeners.get(event)!.push(callback);\n },\n\n /** Configure the chat appearance. */\n configure(config: Partial<ChatConfig>): void {\n // Send config to iframe via postMessage\n if (widgetEl && widgetEl instanceof HTMLIFrameElement) {\n widgetEl.contentWindow?.postMessage({ type: \"g8_chat_config\", config }, \"*\");\n }\n },\n\n /** Close the chat widget. */\n close(): void {\n if (ws) { ws.close(); ws = null; }\n if (widgetEl) { widgetEl.remove(); widgetEl = null; }\n emit(\"close\");\n },\n };\n};\n","import { isServer } from \"./utils\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface CalendarConfig {\n /** Event type slug (e.g. \"demo-30min\") */\n eventType: string;\n /** Username of the host */\n username: string;\n /** Pre-fill attendee info */\n prefill?: { name?: string; email?: string; notes?: string };\n}\n\nexport interface TimeSlot {\n start: string;\n end: string;\n available: boolean;\n}\n\nexport interface Booking {\n uid: string;\n confirmation_url: string;\n start_time: string;\n end_time: string;\n}\n\nexport interface BookingRequest {\n event_type_id: number;\n slot: string;\n attendee: { name: string; email: string; notes?: string };\n}\n\ntype CalendarEvent = \"booked\" | \"cancelled\" | \"slot_selected\";\ntype CalendarCallback = (data: Record<string, unknown>) => void;\n\n/**\n * Calendar and booking - show scheduling widgets, get slots, book meetings.\n *\n * Public endpoints - no API key needed.\n */\nexport const createCalendarClient = (apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n const listeners: Map<CalendarEvent, CalendarCallback[]> = new Map();\n\n return {\n /** Show a booking modal overlay. */\n show(config: CalendarConfig): void {\n if (isServer) return;\n\n const url = `${baseUrl}/appointments/${config.username}/${config.eventType}`;\n const params = new URLSearchParams();\n if (config.prefill?.name) params.set(\"name\", config.prefill.name);\n if (config.prefill?.email) params.set(\"email\", config.prefill.email);\n\n const iframe = document.createElement(\"iframe\");\n iframe.src = `${url}?${params.toString()}`;\n iframe.style.cssText = \"position:fixed;top:0;left:0;width:100%;height:100%;border:none;z-index:99999;background:rgba(0,0,0,0.5);\";\n iframe.id = \"g8-calendar-modal\";\n document.body.appendChild(iframe);\n\n // Close on escape\n const onKey = (e: KeyboardEvent) => { if (e.key === \"Escape\") { iframe.remove(); document.removeEventListener(\"keydown\", onKey); } };\n document.addEventListener(\"keydown\", onKey);\n },\n\n /** Embed booking widget inline in a container element. */\n embed(selector: string, config: CalendarConfig): void {\n if (isServer) return;\n\n const container = document.querySelector(selector);\n if (!container) return;\n\n const url = `${baseUrl}/appointments/${config.username}/${config.eventType}`;\n const iframe = document.createElement(\"iframe\");\n iframe.src = url;\n iframe.style.cssText = \"width:100%;min-height:600px;border:none;border-radius:8px;\";\n container.appendChild(iframe);\n },\n\n /** Get available time slots for an event type. */\n async slots(username: string, eventSlug: string, range: { start: string; end: string }): Promise<TimeSlot[]> {\n const params = new URLSearchParams({\n start_date: range.start,\n end_date: range.end,\n });\n const resp = await fetch(`${baseUrl}/appointments/public/slots?username=${username}&event_slug=${eventSlug}&${params.toString()}`);\n if (!resp.ok) return [];\n const data = await resp.json();\n return data.slots || data.data || [];\n },\n\n /** Book a meeting programmatically. */\n async book(request: BookingRequest): Promise<Booking | null> {\n const resp = await fetch(`${baseUrl}/appointments/public/bookings`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(request),\n });\n if (!resp.ok) return null;\n const data = await resp.json();\n const emit = listeners.get(\"booked\");\n if (emit) emit.forEach((cb) => cb(data));\n return data;\n },\n\n /** Listen for calendar events. */\n on(event: CalendarEvent, callback: CalendarCallback): void {\n if (!listeners.has(event)) listeners.set(event, []);\n listeners.get(event)!.push(callback);\n },\n };\n};\n","/**\n * Hardened HTTP core for the graph8 JS SDK (sprint B2).\n *\n * Resource clients historically called `fetch` directly and returned\n * `resp.json()` even on a 4xx/5xx — so API errors surfaced silently as \"data\".\n * This module centralizes the request path with:\n *\n * - a typed `G8Error` (status, type, code, request_id, detail) thrown on any\n * non-2xx response, parsed from the standard ApiError envelope;\n * - automatic retry with exponential backoff + jitter on 429 and 5xx,\n * honoring the `Retry-After` header;\n * - `Idempotency-Key` support for safe POST retries (pairs with the backend\n * idempotency added in A6);\n * - a cursor `paginate()` async-iterator that follows `next_cursor` (A9).\n *\n * `fetch` and `sleep` are injectable so the retry/backoff logic is\n * deterministically unit-testable without real timers or network.\n */\n\nexport class G8Error extends Error {\n readonly status: number;\n readonly type: string;\n readonly code?: string;\n readonly requestId?: string;\n readonly detail?: unknown;\n /** True when the failure class is transient (429/5xx/network). */\n readonly retryable: boolean;\n\n constructor(args: {\n message: string;\n status: number;\n type: string;\n code?: string;\n requestId?: string;\n detail?: unknown;\n retryable?: boolean;\n }) {\n super(args.message);\n this.name = \"G8Error\";\n this.status = args.status;\n this.type = args.type;\n this.code = args.code;\n this.requestId = args.requestId;\n this.detail = args.detail;\n this.retryable = args.retryable ?? false;\n // Restore prototype chain for `instanceof` across the TS->ES5 downlevel.\n Object.setPrototypeOf(this, G8Error.prototype);\n }\n}\n\n/** 429 and 5xx are the transient classes worth retrying. */\nexport function isRetryableStatus(status: number): boolean {\n return status === 429 || (status >= 500 && status <= 599);\n}\n\n/**\n * Methods that are NOT safe to blind-retry.\n *\n * GET/HEAD/OPTIONS are safe, and PUT/DELETE are idempotent by their HTTP\n * definition — resending them cannot create a second thing. POST and PATCH can,\n * so a retry needs an `Idempotency-Key` to be safe.\n */\nfunction isNonIdempotentMethod(method: string): boolean {\n const m = method.toUpperCase();\n return m === \"POST\" || m === \"PATCH\";\n}\n\n/**\n * Mint an idempotency key for a request the SDK might retry on its own.\n *\n * THE BUG THIS FIXES: this client retries 429/5xx AND network errors for every\n * method, POST included, while `idempotencyKey` was optional and unset by\n * default. So a timeout or a 500 on `POST /contacts` would silently be retried\n * and could create the contact TWICE — a duplicate the caller never asked for\n * and could not see. Generating a key here means the server (which now honours\n * the header on every POST) collapses those retries into one operation.\n *\n * The key is generated ONCE per logical request and reused across that\n * request's retries — a fresh key per attempt would defeat the whole point.\n */\nfunction newIdempotencyKey(): string {\n const c: any = (globalThis as any).crypto;\n if (c?.randomUUID) return c.randomUUID();\n if (c?.getRandomValues) {\n const bytes = c.getRandomValues(new Uint8Array(16));\n return Array.from(bytes as Uint8Array, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n // Last-resort fallback for exotic runtimes with no crypto at all. Weaker, but\n // still far better than retrying with no key: collisions only matter within\n // one credential's 24h replay window.\n return `g8-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`;\n}\n\n/**\n * Parse a `Retry-After` header into milliseconds. Supports both the\n * delta-seconds form (`\"2\"`) and the HTTP-date form. Returns null when absent\n * or unparseable so the caller falls back to computed backoff.\n */\nexport function parseRetryAfter(header: string | null | undefined, nowMs: number = Date.now()): number | null {\n if (!header) return null;\n const secs = Number(header);\n if (Number.isFinite(secs) && secs >= 0) return Math.round(secs * 1000);\n const dateMs = Date.parse(header);\n if (!Number.isNaN(dateMs)) {\n const delta = dateMs - nowMs;\n return delta > 0 ? delta : 0;\n }\n return null;\n}\n\n/** Exponential backoff with full jitter, capped at 10s. */\nexport function backoffDelayMs(attempt: number, baseMs = 200, rand: () => number = Math.random): number {\n const expo = Math.min(baseMs * 2 ** attempt, 10_000);\n return Math.floor(expo / 2 + rand() * (expo / 2));\n}\n\nfunction defaultSleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction buildQuery(query?: Record<string, unknown>): string {\n if (!query) return \"\";\n const qs = new URLSearchParams();\n for (const [k, v] of Object.entries(query)) {\n if (v != null) qs.set(k, String(v));\n }\n const s = qs.toString();\n return s ? `?${s}` : \"\";\n}\n\nasync function toG8Error(resp: Response): Promise<G8Error> {\n let body: unknown = undefined;\n try {\n const text = await resp.text();\n body = text ? JSON.parse(text) : undefined;\n } catch {\n body = undefined;\n }\n const env = (body ?? {}) as Record<string, unknown>;\n const message =\n (typeof env.message === \"string\" && env.message) ||\n (typeof env.error === \"string\" && env.error) ||\n `Request failed with status ${resp.status}`;\n return new G8Error({\n message,\n status: resp.status,\n type: (typeof env.type === \"string\" && env.type) || (typeof env.error === \"string\" && env.error) || \"api_error\",\n code: typeof env.code === \"string\" ? env.code : String(resp.status),\n requestId:\n (typeof env.request_id === \"string\" && env.request_id) || resp.headers.get(\"x-request-id\") || undefined,\n detail: env.detail,\n retryable: isRetryableStatus(resp.status),\n });\n}\n\nexport interface RequestOptions {\n method?: string;\n body?: unknown;\n headers?: Record<string, string>;\n query?: Record<string, unknown>;\n /** Sent as the `Idempotency-Key` header (safe POST retries; see A6). */\n idempotencyKey?: string;\n /** Max retry attempts on 429/5xx/network (default 2 -> up to 3 tries). */\n maxRetries?: number;\n /** Base backoff in ms (default 200). */\n retryBaseMs?: number;\n signal?: AbortSignal;\n /** Injected for tests; defaults to global fetch. */\n fetchImpl?: typeof fetch;\n /** Injected for tests; defaults to a real setTimeout sleep. */\n sleepImpl?: (ms: number) => Promise<void>;\n}\n\n/**\n * Perform a JSON request with retries + typed errors. Returns the parsed JSON\n * envelope (callers unwrap `.data` as today). Throws `G8Error` on any non-2xx\n * after exhausting retries.\n */\nexport async function request<T = unknown>(\n baseUrl: string,\n path: string,\n apiKey: string,\n opts: RequestOptions = {},\n): Promise<T> {\n const {\n method = \"GET\",\n body,\n headers = {},\n query,\n idempotencyKey,\n maxRetries = 2,\n retryBaseMs = 200,\n signal,\n fetchImpl = fetch,\n sleepImpl = defaultSleep,\n } = opts;\n\n const url = baseUrl.replace(/\\/+$/, \"\") + path + buildQuery(query);\n const finalHeaders: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n ...headers,\n };\n // An explicit key always wins. Otherwise mint one for any method this client\n // might retry unsafely, so OUR OWN retry cannot duplicate the caller's write.\n // Skipped entirely when retries are disabled (maxRetries === 0) — with no\n // retry there is nothing to make safe, and the header stays off the wire for\n // callers who never wanted it.\n const effectiveIdempotencyKey =\n idempotencyKey ??\n (maxRetries > 0 && isNonIdempotentMethod(method) ? newIdempotencyKey() : undefined);\n if (effectiveIdempotencyKey) finalHeaders[\"Idempotency-Key\"] = effectiveIdempotencyKey;\n\n let attempt = 0;\n for (;;) {\n let resp: Response;\n try {\n resp = await fetchImpl(url, {\n method,\n headers: finalHeaders,\n body: body == null ? undefined : JSON.stringify(body),\n signal,\n });\n } catch (err) {\n if (attempt < maxRetries) {\n await sleepImpl(backoffDelayMs(attempt, retryBaseMs));\n attempt++;\n continue;\n }\n throw new G8Error({\n message: `Network error: ${(err as Error)?.message ?? \"request failed\"}`,\n status: 0,\n type: \"network_error\",\n retryable: true,\n });\n }\n\n if (resp.ok) {\n const text = await resp.text();\n return (text ? JSON.parse(text) : undefined) as T;\n }\n\n if (isRetryableStatus(resp.status) && attempt < maxRetries) {\n const retryAfter = parseRetryAfter(resp.headers.get(\"retry-after\"));\n const delay = retryAfter != null ? retryAfter : backoffDelayMs(attempt, retryBaseMs);\n await sleepImpl(delay);\n attempt++;\n continue;\n }\n\n throw await toG8Error(resp);\n }\n}\n\nexport interface PaginatedResponse<T> {\n data: T[];\n pagination?: { next_cursor?: string | null; has_next?: boolean; page?: number };\n}\n\n/**\n * Auto-pagination async iterator following `next_cursor` (A9). Yields every\n * item across pages so callers can `for await (const x of paginate(...))`\n * without manual cursor bookkeeping.\n */\nexport async function* paginate<T>(\n fetchPage: (cursor?: string) => Promise<PaginatedResponse<T>>,\n): AsyncGenerator<T, void, unknown> {\n let cursor: string | undefined = undefined;\n for (;;) {\n const page = await fetchPage(cursor);\n for (const item of page.data ?? []) yield item;\n const next = page.pagination?.next_cursor;\n if (!next) break;\n cursor = next;\n }\n}\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface PersonEnrichment {\n found: boolean;\n confidence: number;\n data: Record<string, unknown>;\n}\n\nexport interface CompanyEnrichment {\n found: boolean;\n confidence: number;\n data: Record<string, unknown>;\n}\n\nexport interface EmailVerification {\n email: string;\n valid: boolean;\n deliverable: boolean;\n catch_all: boolean;\n}\n\nexport interface SearchFilter {\n field: string;\n operator: \"any_of\" | \"contains\" | \"all_of\" | \"none_of\" | \"is_empty\" | \"is_not_empty\" | \"between\" | \"exists\";\n value: unknown;\n}\n\nexport interface SearchResults {\n contacts: Record<string, unknown>[];\n total: number;\n page: number;\n}\n\n/**\n * Enrichment API - person/company lookup, email verification, prospecting search.\n *\n * Requires API key (server-side only). Credits charged per call. On the hardened\n * HTTP core: throws a typed `G8Error` on failure and retries transient errors.\n */\nexport const createEnrichClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** Look up a person by email, LinkedIn, or name + company. Costs 1 credit. */\n async person(params: {\n email?: string;\n linkedin_url?: string;\n first_name?: string;\n last_name?: string;\n company_domain?: string;\n }): Promise<PersonEnrichment> {\n const resp = await request<{ data?: PersonEnrichment }>(baseUrl, \"/api/v1/enrichment/lookup/person\", apiKey, {\n method: \"POST\",\n body: params,\n });\n return resp.data ?? (resp as unknown as PersonEnrichment);\n },\n\n /** Look up a company by domain or name. Costs 1 credit. */\n async company(params: { domain?: string; name?: string }): Promise<CompanyEnrichment> {\n const resp = await request<{ data?: CompanyEnrichment }>(baseUrl, \"/api/v1/enrichment/lookup/company\", apiKey, {\n method: \"POST\",\n body: params,\n });\n return resp.data ?? (resp as unknown as CompanyEnrichment);\n },\n\n /** Verify an email address. Costs 1 credit. */\n async verifyEmail(email: string): Promise<EmailVerification> {\n const resp = await request<{ data?: EmailVerification }>(baseUrl, \"/api/v1/enrichment/verify-email\", apiKey, {\n method: \"POST\",\n body: { email },\n });\n return resp.data ?? (resp as unknown as EmailVerification);\n },\n\n /** Search 700M+ contacts with filters. Credits charged per result. */\n async search(filters: SearchFilter[], page = 1, limit = 25): Promise<SearchResults> {\n const resp = await request<{ data?: SearchResults }>(baseUrl, \"/api/v1/search/contacts\", apiKey, {\n method: \"POST\",\n body: { filters, page, limit },\n });\n return resp.data ?? (resp as unknown as SearchResults);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\n// -- Existing types (preserved for backwards compat) --\n\nexport interface Sequence {\n id: string;\n name: string;\n status: string;\n step_count: number | null;\n contact_count: number | null;\n}\n\nexport interface AddToSequenceConfig {\n sequenceId: string;\n contactIds: number[];\n listId: number;\n}\n\n// -- New (0.4.0) types --\n\nexport interface SequenceListItem {\n id: string;\n name: string | null;\n status: string | null;\n user_email: string | null;\n step_count: number | null;\n contact_count: number | null;\n sequence_kind: string | null;\n associated_list_id: number | null;\n created_at: string | null;\n updated_at: string | null;\n}\n\nexport interface SequenceListParams {\n page?: number;\n limit?: number;\n /** Filter by sequence status (e.g. \"live\", \"draft\", \"paused\"). */\n status?: string;\n /** Filter by sequence kind (\"cold_outbound\" or \"nurture\"). Omit to list all kinds. */\n sequence_kind?: SequenceKind;\n}\n\nexport interface SequenceDetail {\n id: string;\n name: string | null;\n description: string | null;\n status: string | null;\n user_email: string | null;\n associated_list_id: number | null;\n finish_on_reply: boolean;\n send_in_same_thread: boolean;\n wait_for_new_contacts: boolean;\n paused_at: string | null;\n resumed_at: string | null;\n /** Sequence kind. Immutable after creation. \"cold_outbound\" (default) or \"nurture\". */\n sequence_kind?: string | null;\n /** Pinned mailbox for nurture sequences; null for cold_outbound. Immutable. */\n pinned_mailbox_id?: number | null;\n created_at: string | null;\n updated_at: string | null;\n}\n\nexport interface SequenceContactItem {\n id: string | null;\n contact_id: number | null;\n state: string | null;\n current_step_order: number | null;\n created_at: string | null;\n updated_at: string | null;\n}\n\nexport interface SequenceContactsParams {\n page?: number;\n limit?: number;\n /** Filter by contact state (e.g. \"active\", \"completed\", \"replied\"). */\n state?: string;\n}\n\nexport interface SequenceActionResult {\n sequence_id: string;\n status: string;\n contacts_affected: number;\n}\n\n/**\n * Step type. Note: LinkedIn flows use \"HEYREACH\" — there is no \"LINKEDIN\" step type.\n * Server is case-insensitive on input but stores uppercase.\n */\nexport type SequenceStepType =\n | \"EMAIL\"\n | \"PHONE\"\n | \"SMS\"\n | \"WHATSAPP\"\n | \"HEYREACH\"\n | \"MANUAL_DIALER\";\n\nexport type SequenceStepInputType =\n | \"ON_DEMAND\"\n | \"MANUAL_TEMPLATE\"\n | \"AI_GENERATED_TEMPLATE\";\n\nexport interface SequenceStepConfig {\n step_order: number;\n step_type: SequenceStepType | string;\n /** Defaults to \"ON_DEMAND\". */\n input_type?: SequenceStepInputType | string;\n /** Wait time before this step in seconds. Defaults to 0. */\n time_interval?: number;\n /** Template body, AI prompt, or other step-type-specific config. */\n step_data?: Record<string, unknown>;\n}\n\nexport interface SequenceChannelConfig {\n channel_id: number;\n channel_value: string;\n channel_type: string;\n channel_data?: Record<string, unknown>;\n}\n\n/**\n * Sequence kind. A \"nurture\" is an ordinary sequence with `sequence_kind:\n * \"nurture\"` — same step types as cold outreach, but pinned to a single mailbox\n * with a higher daily email cap. There is no separate nurture client; create one\n * via `sequences.create({ sequence_kind: \"nurture\", pinned_mailbox_id })`.\n */\nexport type SequenceKind = \"cold_outbound\" | \"nurture\";\n\nexport interface SequenceCreateParams {\n name: string;\n user_email: string;\n description?: string;\n finish_on_reply?: boolean;\n send_in_same_thread?: boolean;\n wait_for_new_contacts?: boolean;\n associated_list_id?: number;\n steps?: SequenceStepConfig[];\n channels?: SequenceChannelConfig[];\n campaign_id?: string;\n /**\n * Sequence kind. Defaults to \"cold_outbound\" server-side. Immutable after\n * creation. \"nurture\" requires `pinned_mailbox_id` and is gated by the\n * ENABLE_NURTURE feature flag.\n */\n sequence_kind?: SequenceKind;\n /**\n * Mailbox to pin for a nurture sequence. Required when\n * `sequence_kind: \"nurture\"`; all email channels must use this mailbox.\n * Ignored for cold_outbound sequences.\n */\n pinned_mailbox_id?: number;\n}\n\nexport interface SequenceCreateResult {\n id: string;\n name: string;\n status: string;\n created_at: string | null;\n}\n\nexport interface SequenceUpdateParams {\n name?: string;\n description?: string;\n is_shared?: boolean;\n finish_on_reply?: boolean;\n send_in_same_thread?: boolean;\n wait_for_new_contacts?: boolean;\n schedule_id?: string;\n appointment_id?: number;\n}\n\nexport interface SequenceStepUpdateParams {\n step_data?: Record<string, unknown>;\n time_interval?: number;\n step_type?: SequenceStepType | string;\n input_type?: SequenceStepInputType | string;\n}\n\nexport interface SequencePreviewStep {\n id: string;\n step_order: number;\n step_type: string;\n input_type: string;\n time_interval: number | null;\n step_data: Record<string, unknown> | null;\n}\n\nexport interface SequencePreviewChannel {\n id: string;\n channel_id: number | null;\n channel_value: string | null;\n channel_type: string | null;\n}\n\nexport interface SequencePreview {\n id: string;\n name: string | null;\n status: string | null;\n description: string | null;\n steps: SequencePreviewStep[];\n channels: SequencePreviewChannel[];\n}\n\nexport interface SequenceAnalytics {\n overview: Record<string, unknown>;\n performance: Record<string, unknown>;\n engagement: Record<string, unknown>;\n timeline: Record<string, unknown>[];\n contact_distribution: Record<string, unknown>;\n step_breakdown: Record<string, unknown>[];\n step_creation_methods: Record<string, unknown>[];\n sender_distribution: Record<string, unknown>[];\n}\n\nexport interface PaginationMeta {\n page: number;\n limit: number;\n total: number;\n has_next: boolean;\n}\n\n/**\n * Sequences API — list, create, run, pause, update, analyze multi-channel sequences.\n * Requires API key (server-side).\n *\n * Backed by:\n * GET /api/v1/sequences\n * POST /api/v1/sequences\n * GET /api/v1/sequences/{sequence_id}\n * PATCH /api/v1/sequences/{sequence_id}\n * DELETE /api/v1/sequences/{sequence_id}\n * GET /api/v1/sequences/{sequence_id}/contacts\n * POST /api/v1/sequences/{sequence_id}/contacts\n * POST /api/v1/sequences/{sequence_id}/run\n * POST /api/v1/sequences/{sequence_id}/pause\n * POST /api/v1/sequences/{sequence_id}/resume\n * PATCH /api/v1/sequences/{sequence_id}/steps/{step_id}\n * GET /api/v1/sequences/{sequence_id}/preview\n * GET /api/v1/sequences/{sequence_id}/analytics\n */\nexport const createSequencesClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n // -- Overloads on list() preserve backwards compat with v0.3.0's positional signature --\n\n async function list(): Promise<SequenceListItem[]>;\n async function list(page: number, limit?: number): Promise<SequenceListItem[]>;\n async function list(params: SequenceListParams): Promise<SequenceListItem[]>;\n async function list(\n pageOrParams?: number | SequenceListParams,\n limit?: number,\n ): Promise<SequenceListItem[]> {\n let params: SequenceListParams;\n if (typeof pageOrParams === \"number\") {\n params = { page: pageOrParams, limit: limit ?? 50 };\n } else {\n params = pageOrParams ?? {};\n }\n const resp = await request<{ data?: SequenceListItem[] }>(baseUrl, \"/api/v1/sequences\", apiKey, {\n query: params as Record<string, unknown>,\n });\n return (resp.data ?? (resp as unknown as SequenceListItem[])) as SequenceListItem[];\n }\n\n return {\n /** List sequences with pagination + optional status filter. */\n list,\n\n /** Get full sequence details by ID. */\n async get(sequenceId: string): Promise<SequenceDetail> {\n const resp = await request<{ data?: SequenceDetail }>(baseUrl, `/api/v1/sequences/${sequenceId}`, apiKey);\n return resp.data ?? (resp as unknown as SequenceDetail);\n },\n\n /** List contacts enrolled in a sequence. Filter by state (e.g. \"active\", \"replied\"). */\n async contacts(\n sequenceId: string,\n params: SequenceContactsParams = {},\n ): Promise<{ data: SequenceContactItem[]; pagination?: PaginationMeta }> {\n return request(baseUrl, `/api/v1/sequences/${sequenceId}/contacts`, apiKey, {\n query: params as Record<string, unknown>,\n });\n },\n\n /**\n * Add contacts to a sequence (V2 queuing). Live or drafted sequences only.\n * Pass `idempotencyKey` to make a retry safe — the same key returns the\n * first result instead of re-enrolling on a 5xx-then-success (A6).\n */\n async add(config: AddToSequenceConfig, idempotencyKey?: string): Promise<SequenceActionResult> {\n const resp = await request<{ data?: SequenceActionResult }>(\n baseUrl,\n `/api/v1/sequences/${config.sequenceId}/contacts`,\n apiKey,\n { method: \"POST\", body: { contact_ids: config.contactIds, list_id: config.listId }, idempotencyKey },\n );\n return resp.data ?? (resp as unknown as SequenceActionResult);\n },\n\n /**\n * Create a new sequence with optional steps + channels. Pass `idempotencyKey`\n * to make a retry safe — the same key returns the first result instead of\n * creating a duplicate sequence on a 5xx-then-success (A6).\n */\n async create(payload: SequenceCreateParams, idempotencyKey?: string): Promise<SequenceCreateResult> {\n const resp = await request<{ data?: SequenceCreateResult }>(baseUrl, \"/api/v1/sequences\", apiKey, {\n method: \"POST\",\n body: payload,\n idempotencyKey,\n });\n return resp.data ?? (resp as unknown as SequenceCreateResult);\n },\n\n /** Update sequence metadata. Rejected (409) if sequence is in a transitional status. */\n async update(sequenceId: string, fields: SequenceUpdateParams): Promise<SequenceActionResult> {\n const resp = await request<{ data?: SequenceActionResult }>(baseUrl, `/api/v1/sequences/${sequenceId}`, apiKey, {\n method: \"PATCH\",\n body: fields,\n });\n return resp.data ?? (resp as unknown as SequenceActionResult);\n },\n\n /** Update a single step within a sequence. */\n async updateStep(\n sequenceId: string,\n stepId: string,\n fields: SequenceStepUpdateParams,\n ): Promise<SequenceActionResult> {\n const resp = await request<{ data?: SequenceActionResult }>(\n baseUrl,\n `/api/v1/sequences/${sequenceId}/steps/${stepId}`,\n apiKey,\n { method: \"PATCH\", body: fields },\n );\n return resp.data ?? (resp as unknown as SequenceActionResult);\n },\n\n /** Soft-delete (archive) a sequence. */\n async delete(sequenceId: string): Promise<SequenceActionResult> {\n const resp = await request<{ data?: SequenceActionResult }>(baseUrl, `/api/v1/sequences/${sequenceId}`, apiKey, {\n method: \"DELETE\",\n });\n return resp.data ?? (resp as unknown as SequenceActionResult);\n },\n\n /**\n * Run/start a DRAFTED sequence (V2 orchestration). Pass `idempotencyKey` to\n * make a retry safe — the same key won't re-trigger the run on a\n * 5xx-then-success (A6).\n */\n async run(sequenceId: string, idempotencyKey?: string): Promise<SequenceActionResult> {\n const resp = await request<{ data?: SequenceActionResult }>(\n baseUrl,\n `/api/v1/sequences/${sequenceId}/run`,\n apiKey,\n { method: \"POST\", idempotencyKey },\n );\n return resp.data ?? (resp as unknown as SequenceActionResult);\n },\n\n /**\n * Pause a live sequence. Pass `idempotencyKey` to make a retry safe — the\n * same key won't double-apply on a 5xx-then-success (A6).\n */\n async pause(sequenceId: string, idempotencyKey?: string): Promise<SequenceActionResult> {\n const resp = await request<{ data?: SequenceActionResult }>(\n baseUrl,\n `/api/v1/sequences/${sequenceId}/pause`,\n apiKey,\n { method: \"POST\", idempotencyKey },\n );\n return resp.data ?? (resp as unknown as SequenceActionResult);\n },\n\n /**\n * Resume a paused sequence. Pass `idempotencyKey` to make a retry safe — the\n * same key won't double-apply on a 5xx-then-success (A6).\n */\n async resume(sequenceId: string, idempotencyKey?: string): Promise<SequenceActionResult> {\n const resp = await request<{ data?: SequenceActionResult }>(\n baseUrl,\n `/api/v1/sequences/${sequenceId}/resume`,\n apiKey,\n { method: \"POST\", idempotencyKey },\n );\n return resp.data ?? (resp as unknown as SequenceActionResult);\n },\n\n /** Read-only sequence preview with all steps + channels (no enrollment). */\n async preview(sequenceId: string): Promise<SequencePreview> {\n const resp = await request<{ data?: SequencePreview }>(baseUrl, `/api/v1/sequences/${sequenceId}/preview`, apiKey);\n return resp.data ?? (resp as unknown as SequencePreview);\n },\n\n /** Comprehensive analytics for a sequence. */\n async analytics(sequenceId: string): Promise<SequenceAnalytics> {\n const resp = await request<{ data?: SequenceAnalytics }>(\n baseUrl,\n `/api/v1/sequences/${sequenceId}/analytics`,\n apiKey,\n );\n return resp.data ?? (resp as unknown as SequenceAnalytics);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface Campaign {\n id: string;\n name: string;\n slug: string;\n status: string;\n category: string | null;\n goal: string | null;\n target_persona: string | null;\n}\n\nexport interface CampaignCreateConfig {\n name: string;\n category?: string;\n brief?: string;\n core_concept?: string;\n primary_hook?: string;\n target_persona?: string;\n goal?: string;\n}\n\nexport interface CampaignLaunchExecution {\n status: string;\n contacts_total?: number;\n contacts_scheduled?: number;\n contacts_queued?: number;\n job_id?: string;\n polling_url?: string;\n orchestrator_version?: string;\n}\n\nexport interface CampaignLaunchResult {\n status: string;\n campaign_id: string;\n sequence_id: string;\n sequence_name: string;\n steps_created: number;\n link_id: string;\n warnings: string[];\n channels_attached: Array<{\n mailbox_id: number;\n email: string;\n channel_type: string;\n auto_picked: boolean;\n }>;\n agent_assigned: {\n textual_agent_name: string | null;\n voice_agent_name: string | null;\n };\n schedule_id: string | null;\n appointment_id: number | null;\n execution: CampaignLaunchExecution;\n message: string;\n}\n\n/**\n * Campaigns - create, manage, launch campaigns. Requires API key (server-side).\n * On the hardened HTTP core: throws a typed `G8Error` on failure and retries\n * transient errors.\n */\nexport const createCampaignsClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n async list(page = 1, limit = 50): Promise<Campaign[]> {\n const resp = await request<{ data?: Campaign[] }>(baseUrl, \"/api/v1/campaigns\", apiKey, {\n query: { page, limit },\n });\n return resp.data ?? (resp as unknown as Campaign[]);\n },\n\n async get(campaignId: string): Promise<Campaign> {\n const resp = await request<{ data?: Campaign }>(baseUrl, `/api/v1/campaigns/${campaignId}`, apiKey);\n return resp.data ?? (resp as unknown as Campaign);\n },\n\n async create(config: CampaignCreateConfig): Promise<Campaign> {\n const resp = await request<{ data?: Campaign }>(baseUrl, \"/api/v1/campaigns\", apiKey, {\n method: \"POST\",\n body: config,\n });\n return resp.data ?? (resp as unknown as Campaign);\n },\n\n async launch(campaignId: string): Promise<CampaignLaunchResult> {\n const resp = await request<{ data?: CampaignLaunchResult }>(\n baseUrl,\n `/api/v1/campaigns/${campaignId}/launch`,\n apiKey,\n { method: \"POST\" },\n );\n return resp.data ?? (resp as unknown as CampaignLaunchResult);\n },\n };\n};\n","const DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface IntentSignals {\n domain: string;\n score: number;\n intent: \"low\" | \"medium\" | \"high\";\n signals: string[];\n last_seen: string | null;\n}\n\n/**\n * Intent signals - company-level buying signals. Write key for public, API key for full access.\n */\nexport const createSignalsClient = (key: string, isApiKey: boolean, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n const headers = (): Record<string, string> => isApiKey\n ? { \"Content-Type\": \"application/json\", \"Authorization\": `Bearer ${key}` }\n : { \"Content-Type\": \"application/json\", \"X-Write-Key\": key };\n\n // There is exactly ONE intent-signals route in the platform:\n // `/api/v1/public/signals/company` (developer_api/interfaces/v1/public_signals_router.py).\n //\n // This used to branch to `/api/v1/signals/company` for API-key callers. That\n // route has never existed at any prefix — the request 404'd, and the `!resp.ok`\n // guard below swallowed it into an all-zeros result, so a server-side caller\n // saw \"no intent\" rather than an error. Pointing both credential types at the\n // route that exists removes the phantom endpoint.\n //\n // KNOWN GAP (not fixed here, needs a product decision): the live route\n // authenticates with `validate_write_key`, which requires an `X-Write-Key`\n // header and rejects `Authorization: Bearer`. So an API-key-only caller still\n // cannot read signals — it now gets a 401 instead of a 404, both swallowed to\n // zeros. Closing that needs a server-side signals endpoint that accepts API\n // keys; until then, pass a `writeKey` to `g8.init()` to use this surface.\n const endpoint = \"/api/v1/public/signals/company\";\n\n return {\n /** Get intent signals for a specific company domain. */\n async company(domain: string): Promise<IntentSignals> {\n const resp = await fetch(`${baseUrl}${endpoint}?domain=${encodeURIComponent(domain)}`, { headers: headers() });\n if (!resp.ok) return { domain, score: 0, intent: \"low\", signals: [], last_seen: null };\n const data = await resp.json();\n return data.data || data;\n },\n\n /** Stream intent signals - calls callback every 30s with latest data. */\n stream(domains: string[], callback: (signals: IntentSignals[]) => void): () => void {\n const check = async () => {\n try {\n const results = await Promise.all(domains.map((d) => this.company(d)));\n callback(results);\n } catch { /* silent */ }\n };\n\n check();\n const interval = setInterval(check, 30_000);\n return () => clearInterval(interval);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\ntype VoiceEvent = \"connected\" | \"transcription\" | \"ended\" | \"error\";\ntype VoiceCallback = (data: Record<string, unknown>) => void;\n\n// -- New (0.4.0) dialer types — backed by /api/v1/voice/dialer/* --\n\nexport interface VoicePagination {\n total_items: number;\n total_pages: number;\n current_page: number;\n page_size: number;\n}\n\nexport interface DialerSessionSummary {\n session_id: string;\n status: string | null;\n user_id: string | null;\n user_email: string | null;\n org_id: string | null;\n from_phone: string | null;\n campaign_id: string | null;\n campaign_builder_campaign_id: string | null;\n name: string | null;\n session_metadata: Record<string, unknown> | null;\n total_calls: number | null;\n created_at: string | null;\n updated_at: string | null;\n contact_ids: unknown[];\n}\n\nexport interface DialerSessionsListResult {\n sessions: DialerSessionSummary[];\n pagination: VoicePagination;\n}\n\nexport interface DialerSessionsListParams {\n page?: number;\n /** Default 50, max 200. */\n page_size?: number;\n /** Comma-separated status list (e.g. \"ACTIVE,PAUSED\"). */\n status?: string;\n user_email?: string;\n /** Substring search on session name. */\n name?: string;\n campaign_id?: string;\n list_id?: string;\n list_name?: string;\n /** ISO 8601 timestamp. */\n date_from?: string;\n /** ISO 8601 timestamp. */\n date_to?: string;\n sort_by?: string;\n /** Default \"desc\". */\n sort_order?: \"asc\" | \"desc\";\n}\n\nexport interface DialerStatsParams {\n session_id?: string;\n user_email?: string;\n /** YYYY-MM-DD. */\n date_from?: string;\n /** YYYY-MM-DD. */\n date_to?: string;\n /** Default \"DAILY\". */\n aggregation?: \"DAILY\" | \"TOTAL\";\n}\n\nexport interface DialerReportFilters {\n session_id: string | null;\n user_email: string | null;\n org_id: string | null;\n date_from: string | null;\n date_to: string | null;\n aggregation: string | null;\n}\n\nexport interface DialerReportMetric {\n date: string | null;\n sdr_name: string | null;\n org_id: string | null;\n list_title: string | null;\n total_dials: number;\n total_connections: number;\n connection_rate: number;\n total_voicemails: number;\n voicemail_rate: number;\n talk_time_minutes: number;\n avg_call_duration_minutes: number;\n dispositions: Record<string, unknown> | null;\n success_rate: number;\n unique_sessions: number;\n avg_calls_per_session: number;\n redial_count: number;\n redial_success_rate: number | null;\n peak_calling_hour: number | null;\n total_callbacks: number;\n}\n\nexport interface DialerStatsResult {\n filters: DialerReportFilters;\n metrics: DialerReportMetric[];\n summary: DialerReportMetric | null;\n}\n\nexport interface DialerNumberInfo {\n number: string;\n /** Default \"ai\". */\n inbound_type: string;\n /** Default \"twilio\". */\n telephony_provider: string;\n calls_today: number;\n calls_7d: number;\n connect_rate_7d: number;\n is_valid: boolean;\n daily_limit: number;\n assigned_to: string | null;\n created_at: string | null;\n}\n\nexport interface DialerNumbersListResult {\n numbers: DialerNumberInfo[];\n}\n\nexport interface MissedCallback {\n id: string | number | null;\n caller_phone: string | null;\n inbound_number: string | null;\n first_name: string | null;\n last_name: string | null;\n email: string | null;\n contact_id: string | number | null;\n parallel_session_id: string | null;\n created_at: string | null;\n call_duration: number | null;\n is_callback: boolean;\n}\n\nexport interface MissedCallbacksResult {\n missed_callbacks: MissedCallback[];\n count: number;\n}\n\nexport interface CallGradingResult {\n room_name: string;\n /** \"ready\" or \"pending\". */\n status: string;\n grading: Record<string, unknown> | null;\n reviewed: boolean;\n reviewed_at: string | null;\n}\n\nexport interface DialerAgentSummary {\n agent_id: string;\n agent_name: string | null;\n /** \"SDR\", etc. */\n role: string | null;\n agent_status: string | null;\n /** \"agent\" or \"twin\". */\n entity_type: string | null;\n description: string | null;\n phone: string | null;\n is_template: boolean;\n}\n\nexport interface DialerAgentsListResult {\n agents: DialerAgentSummary[];\n total_count: number;\n}\n\nexport interface DialerAgentsListParams {\n /** e.g. \"SDR\". */\n role?: string;\n agent_status?: string;\n /** \"agent\" or \"twin\". */\n entity_type?: \"agent\" | \"twin\";\n /** Substring filter on name/description. */\n search?: string;\n}\n\nexport interface DialerSessionCreateParams {\n /** 1-200 chars. */\n name: string;\n /** Org's dialer phone (E.164, 9-16 chars). */\n from_phone: string;\n /** Contact list ID (stored in session metadata). */\n list_id?: string;\n /** Display title for the source list. */\n list_title?: string;\n /** V2 agent UUID. */\n agent_id?: string;\n /** V1 fallback name. Defaults to \"default_agent\". */\n agent_name?: string;\n /** \"agent\" or \"twin\". */\n entity_type?: \"agent\" | \"twin\";\n /** Campaign Builder UUID. */\n studio_campaign_id?: string;\n /** IANA timezone (e.g. \"America/New_York\"). */\n user_timezone?: string;\n /** Per-session voicemail-skip override. null/omit = use SDR default. */\n skip_voicemails?: boolean;\n}\n\nexport interface DialerSessionCreateResult {\n session_id: string;\n status: string;\n name: string | null;\n org_id: string | null;\n user_id: string | null;\n user_email: string | null;\n from_phone: string | null;\n session_metadata: Record<string, unknown> | null;\n total_calls: number;\n created_at: string | null;\n message: string | null;\n}\n\n/** \"ACTIVE\" resumes, \"PAUSED\" pauses, \"COMPLETED\" stops. \"FAILED\" is rejected. */\nexport type DialerSessionStatus = \"ACTIVE\" | \"PAUSED\" | \"COMPLETED\";\n\nexport interface DialerSessionStatusUpdateResult {\n session_id: string;\n status: string;\n message: string | null;\n name: string | null;\n org_id: string | null;\n user_id: string | null;\n user_email: string | null;\n from_phone: string | null;\n session_metadata: Record<string, unknown> | null;\n total_calls: number;\n created_at: string | null;\n updated_at: string | null;\n}\n\nexport interface DialerSessionResumeResult extends DialerSessionStatusUpdateResult {\n /** Contacts actually placed in this batch (voice caps at 4). */\n dialed_count: number;\n}\n\n/**\n * Voice AI — start AI voice calls, get transcriptions and analysis.\n * Plus full parallel-dialer session control via the `dialer` namespace.\n * Requires API key (server-side).\n *\n * Backed by:\n * GET /api/v1/voice/dialer/sessions\n * POST /api/v1/voice/dialer/sessions\n * PATCH /api/v1/voice/dialer/sessions/{session_id}/status\n * POST /api/v1/voice/dialer/sessions/{session_id}/resume\n * GET /api/v1/voice/dialer/stats\n * GET /api/v1/voice/dialer/numbers\n * GET /api/v1/voice/dialer/missed-callbacks\n * GET /api/v1/voice/dialer/calls/{room_name}/grading\n * GET /api/v1/voice/dialer/agents\n */\nexport const createVoiceClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n const listeners: Map<VoiceEvent, VoiceCallback[]> = new Map();\n\n const dialer = {\n /** List parallel-dialer sessions with filters + pagination. */\n async listSessions(params: DialerSessionsListParams = {}): Promise<DialerSessionsListResult> {\n const resp = await request<{ data?: DialerSessionsListResult }>(\n baseUrl,\n \"/api/v1/voice/dialer/sessions\",\n apiKey,\n { query: params as Record<string, unknown> },\n );\n return resp.data ?? (resp as unknown as DialerSessionsListResult);\n },\n\n /** Create a parallel-dialer session in PAUSED state. SDR opens UI to start dialing. */\n async createSession(payload: DialerSessionCreateParams): Promise<DialerSessionCreateResult> {\n const resp = await request<{ data?: DialerSessionCreateResult }>(\n baseUrl,\n \"/api/v1/voice/dialer/sessions\",\n apiKey,\n { method: \"POST\", body: payload },\n );\n return resp.data ?? (resp as unknown as DialerSessionCreateResult);\n },\n\n /** Pause / resume / stop a dialer session via status flip. */\n async updateSessionStatus(\n sessionId: string,\n status: DialerSessionStatus,\n ): Promise<DialerSessionStatusUpdateResult> {\n const resp = await request<{ data?: DialerSessionStatusUpdateResult }>(\n baseUrl,\n `/api/v1/voice/dialer/sessions/${sessionId}/status`,\n apiKey,\n { method: \"PATCH\", body: { status } },\n );\n return resp.data ?? (resp as unknown as DialerSessionStatusUpdateResult);\n },\n\n /**\n * Resume a PAUSED dialer session. Auto-fetches the next batch from the source list,\n * filters already-called + phoneless rows, and forwards to voice's start-session.\n * @param maxContacts 1-4 (voice caps parallel dialing at 4). Default 4.\n */\n async resumeSession(sessionId: string, maxContacts = 4): Promise<DialerSessionResumeResult> {\n const resp = await request<{ data?: DialerSessionResumeResult }>(\n baseUrl,\n `/api/v1/voice/dialer/sessions/${sessionId}/resume`,\n apiKey,\n { method: \"POST\", body: { max_contacts: maxContacts } },\n );\n return resp.data ?? (resp as unknown as DialerSessionResumeResult);\n },\n\n /** Aggregated dialer analytics (daily breakdown or total). */\n async stats(params: DialerStatsParams = {}): Promise<DialerStatsResult> {\n const resp = await request<{ data?: DialerStatsResult }>(\n baseUrl,\n \"/api/v1/voice/dialer/stats\",\n apiKey,\n { query: params as Record<string, unknown> },\n );\n return resp.data ?? (resp as unknown as DialerStatsResult);\n },\n\n /** List dialer-eligible phone numbers with 7-day stats + daily limits. */\n async numbers(userEmail?: string): Promise<DialerNumbersListResult> {\n const resp = await request<{ data?: DialerNumbersListResult }>(\n baseUrl,\n \"/api/v1/voice/dialer/numbers\",\n apiKey,\n { query: userEmail ? { user_email: userEmail } : {} },\n );\n return resp.data ?? (resp as unknown as DialerNumbersListResult);\n },\n\n /** List missed inbound callbacks with caller / contact info. */\n async missedCallbacks(limit = 50): Promise<MissedCallbacksResult> {\n const resp = await request<{ data?: MissedCallbacksResult }>(\n baseUrl,\n \"/api/v1/voice/dialer/missed-callbacks\",\n apiKey,\n { query: { limit } },\n );\n return resp.data ?? (resp as unknown as MissedCallbacksResult);\n },\n\n /** AI grading for a single dialer call (returns \"pending\" while in progress). */\n async callGrading(roomName: string): Promise<CallGradingResult> {\n const resp = await request<{ data?: CallGradingResult }>(\n baseUrl,\n `/api/v1/voice/dialer/calls/${encodeURIComponent(roomName)}/grading`,\n apiKey,\n );\n return resp.data ?? (resp as unknown as CallGradingResult);\n },\n\n /** List voice agents available for dialer sessions (capped at 100; no pagination). */\n async agents(params: DialerAgentsListParams = {}): Promise<DialerAgentsListResult> {\n const resp = await request<{ data?: DialerAgentsListResult }>(\n baseUrl,\n \"/api/v1/voice/dialer/agents\",\n apiKey,\n { query: params as Record<string, unknown> },\n );\n return resp.data ?? (resp as unknown as DialerAgentsListResult);\n },\n\n /** Fetch the full transcript for a single dialer call. */\n async callTranscript(roomName: string): Promise<{ data: { status: string; transcript: Array<{ speaker: string; text: string; timestamp: number }> } }> {\n return request(\n baseUrl,\n `/api/v1/voice/dialer/calls/${encodeURIComponent(roomName)}/transcript`,\n apiKey,\n );\n },\n\n /** List dialer calls — pass `contact_id` or `user_email` to scope. */\n async listCalls(params: { contact_id?: number; user_email?: string; campaign_id?: string; date_from?: string; date_to?: string; limit?: number; page?: number } = {}): Promise<{ data: Array<Record<string, unknown>>; pagination?: VoicePagination }> {\n return request(\n baseUrl,\n \"/api/v1/voice/dialer/calls\",\n apiKey,\n { query: params as Record<string, unknown> },\n );\n },\n\n /** Convenience: list calls for a single contact. */\n async listCallsForContact(contactId: number, extra: { limit?: number } = {}): Promise<{ data: Array<Record<string, unknown>> }> {\n return request(\n baseUrl,\n \"/api/v1/voice/dialer/calls\",\n apiKey,\n { query: { contact_id: contactId, ...extra } },\n );\n },\n\n /** Convenience: list calls placed by a specific SDR. */\n async listCallsForSdr(userEmail: string, extra: { limit?: number; date_from?: string; date_to?: string } = {}): Promise<{ data: Array<Record<string, unknown>> }> {\n return request(\n baseUrl,\n \"/api/v1/voice/dialer/calls\",\n apiKey,\n { query: { user_email: userEmail, ...extra } },\n );\n },\n };\n\n return {\n /** Listen for voice events. */\n on(event: VoiceEvent, callback: VoiceCallback): void {\n if (!listeners.has(event)) listeners.set(event, []);\n listeners.get(event)!.push(callback);\n },\n\n /** Parallel-dialer session control + analytics. */\n dialer,\n };\n};\n","import { createHmac, timingSafeEqual } from \"node:crypto\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\n/**\n * Known graph8 webhook event types.\n *\n * Source of truth is the backend ``WEBHOOK_EVENTS`` catalog\n * (campaign_builder/services/webhook_service.py). Keep in sync when the backend\n * adds events. ``WebhookEvent`` also accepts any string so a newly-added\n * backend event never breaks a client that hasn't upgraded.\n */\nexport const KNOWN_WEBHOOK_EVENTS = [\n \"campaign.created\",\n \"campaign.updated\",\n \"campaign.deleted\",\n \"campaign.launched\",\n \"campaign.paused\",\n \"campaign.completed\",\n \"campaign.status_changed\",\n \"campaign.content_ready\",\n \"document.generated\",\n \"document.failed\",\n \"intelligence.completed\",\n \"intelligence.failed\",\n \"company.enriched\",\n \"company_intelligence.completed\",\n \"audience.ready\",\n \"audience.failed\",\n \"sequence.draft_created\",\n \"sequence.started\",\n \"sequence.paused\",\n \"sequence.completed\",\n \"engagement.email_sent\",\n \"engagement.email_replied\",\n \"engagement.email_bounced\",\n \"engagement.email_skipped\",\n \"engagement.call_dispatched\",\n \"engagement.sms_sent\",\n \"engagement.sms_replied\",\n \"engagement.whatsapp_sent\",\n \"engagement.linkedin_connection_sent\",\n \"engagement.linkedin_message_sent\",\n \"engagement.linkedin_inmail_sent\",\n \"engagement.linkedin_reply_received\",\n \"engagement.linkedin_connection_accepted\",\n \"meeting.booked\",\n \"meeting.cancelled\",\n \"meeting.rescheduled\",\n] as const;\n\n// Union of known events for autocomplete, plus `string` so unknown/new backend\n// events still type-check (Stripe-style forward compatibility).\nexport type WebhookEvent = (typeof KNOWN_WEBHOOK_EVENTS)[number] | (string & {});\n\n/** The decoded body graph8 delivers to a webhook endpoint. */\nexport interface WebhookEventPayload {\n event: WebhookEvent;\n timestamp: string;\n data: Record<string, unknown>;\n org_id: string;\n /** Stable per-delivery id (present once the backend adds it; for consumer dedup). */\n id?: string;\n}\n\nexport interface ConstructEventOptions {\n /**\n * Reject events whose ``X-Studio-Timestamp`` is older (or newer) than this\n * many seconds — replay protection. Disabled when 0/undefined.\n */\n toleranceSeconds?: number;\n}\n\n/** Thrown by {@link constructEvent} when a webhook cannot be verified. */\nexport class WebhookSignatureError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"WebhookSignatureError\";\n }\n}\n\nfunction timingSafeEqualHex(a: string, b: string): boolean {\n // Length check first: timingSafeEqual throws on length mismatch.\n if (a.length !== b.length) return false;\n try {\n const enc = new TextEncoder();\n return timingSafeEqual(enc.encode(a), enc.encode(b));\n } catch {\n return false;\n }\n}\n\n/**\n * Verify the HMAC-SHA256 signature of an incoming graph8 webhook and return the\n * parsed event. Server-side only (needs the per-endpoint signing secret).\n *\n * Mirrors the backend signing scheme exactly: the signature is\n * ``HMAC_SHA256(secret, `${timestamp}.${rawBody}`)`` hex-encoded, delivered in\n * the ``X-Studio-Signature`` header alongside the unix ``X-Studio-Timestamp``.\n *\n * @param payload The RAW request body string (verify before JSON.parse — re-serializing changes bytes).\n * @param signature The ``X-Studio-Signature`` header (an optional ``sha256=`` prefix is tolerated).\n * @param timestamp The ``X-Studio-Timestamp`` header (unix seconds).\n * @param secret The endpoint's signing secret.\n * @throws {WebhookSignatureError} on a missing/invalid signature, stale timestamp, or bad JSON.\n *\n * @example\n * app.post(\"/webhooks/graph8\", (req, res) => {\n * const event = g8.webhooks.constructEvent(\n * req.rawBody,\n * req.header(\"X-Studio-Signature\"),\n * req.header(\"X-Studio-Timestamp\"),\n * process.env.G8_WEBHOOK_SECRET,\n * { toleranceSeconds: 300 },\n * );\n * if (event.event === \"meeting.booked\") { ... }\n * res.sendStatus(200);\n * });\n */\nexport function constructEvent(\n payload: string,\n signature: string,\n timestamp: string | number,\n secret: string,\n opts: ConstructEventOptions = {},\n): WebhookEventPayload {\n if (!signature) throw new WebhookSignatureError(\"Missing X-Studio-Signature header\");\n if (timestamp === undefined || timestamp === null || timestamp === \"\") {\n throw new WebhookSignatureError(\"Missing X-Studio-Timestamp header\");\n }\n if (!secret) throw new WebhookSignatureError(\"Missing signing secret\");\n\n const ts = typeof timestamp === \"number\" ? timestamp : parseInt(timestamp, 10);\n if (!Number.isFinite(ts)) throw new WebhookSignatureError(\"Invalid X-Studio-Timestamp header\");\n\n const tolerance = opts.toleranceSeconds ?? 0;\n if (tolerance > 0) {\n const ageSeconds = Math.floor(Date.now() / 1000) - ts;\n if (Math.abs(ageSeconds) > tolerance) {\n throw new WebhookSignatureError(`Timestamp outside tolerance (${ageSeconds}s > ${tolerance}s)`);\n }\n }\n\n const expected = createHmac(\"sha256\", secret).update(`${ts}.${payload}`).digest(\"hex\");\n const provided = signature.startsWith(\"sha256=\") ? signature.slice(7) : signature;\n if (!timingSafeEqualHex(expected, provided)) {\n throw new WebhookSignatureError(\"Signature verification failed\");\n }\n\n try {\n return JSON.parse(payload) as WebhookEventPayload;\n } catch {\n throw new WebhookSignatureError(\"Invalid JSON payload\");\n }\n}\n\n/**\n * Webhooks client (server-side). graph8 webhooks are PUSH — graph8 POSTs to your\n * endpoint; you verify each delivery with {@link constructEvent}. (The previous\n * polling implementation hit a feed endpoint that never existed and is removed.)\n */\nexport const createWebhooksClient = (_apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n return {\n /** Base URL the webhook subscription API lives under. */\n baseUrl,\n /** Known event types (for autocomplete / validation). */\n knownEvents: KNOWN_WEBHOOK_EVENTS,\n /** Verify an incoming webhook's HMAC signature and return the parsed event. */\n constructEvent(\n payload: string,\n signature: string,\n timestamp: string | number,\n secret: string,\n opts?: ConstructEventOptions,\n ): WebhookEventPayload {\n return constructEvent(payload, signature, timestamp, secret, opts);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface Contact {\n id: number;\n first_name: string | null;\n last_name: string | null;\n work_email: string | null;\n job_title: string | null;\n seniority_level: string | null;\n company_name: string | null;\n company_domain: string | null;\n linkedin_url: string | null;\n direct_phone: string | null;\n mobile_phone: string | null;\n city: string | null;\n state: string | null;\n country: string | null;\n}\n\nexport interface ContactListParams {\n page?: number;\n limit?: number;\n email?: string;\n name?: string;\n job_title?: string;\n seniority_level?: string;\n company_name?: string;\n country?: string;\n list_id?: number;\n}\n\nexport interface ContactCreateParams {\n work_email: string;\n first_name?: string;\n last_name?: string;\n job_title?: string;\n company_domain?: string;\n linkedin_url?: string;\n direct_phone?: string;\n mobile_phone?: string;\n city?: string;\n state?: string;\n country?: string;\n list_id?: number;\n}\n\nexport interface ContactUpdateParams {\n first_name?: string;\n last_name?: string;\n work_email?: string;\n job_title?: string;\n company_domain?: string;\n linkedin_url?: string;\n direct_phone?: string;\n mobile_phone?: string;\n city?: string;\n state?: string;\n country?: string;\n}\n\n/** A column definition on contacts (base or custom). */\nexport interface ContactColumn {\n id: number | null;\n title: string;\n data_type: string;\n name: string | null;\n /** Stringified list_id when list-scoped, otherwise null/empty for global. */\n object_id: string | null;\n is_global: boolean;\n}\n\nexport interface ContactColumnCreateParams {\n title: string;\n /** Email of the user creating the column. Required by the backend (audit). */\n created_by: string;\n /** \"text\" (default) — additional types may be added later. */\n data_type?: string;\n /** If set, the column is list-specific. Omit for org-wide global column. */\n list_id?: number;\n}\n\n/**\n * Contacts API - full CRUD for CRM contacts. Requires API key (server-side).\n */\nexport const createContactsClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** List contacts with optional filters. */\n async list(params: ContactListParams = {}): Promise<{ data: Contact[]; total: number }> {\n return request(baseUrl, \"/api/v1/contacts\", apiKey, {\n query: params as Record<string, unknown>,\n });\n },\n\n /** Get a single contact by ID. */\n async get(contactId: number): Promise<Contact> {\n const resp = await request<{ data?: Contact }>(baseUrl, `/api/v1/contacts/${contactId}`, apiKey);\n return resp.data ?? (resp as unknown as Contact);\n },\n\n /**\n * Create a new contact. Pass `idempotencyKey` to make a retry safe — the\n * same key returns the first result instead of creating a duplicate (A6).\n */\n async create(contact: ContactCreateParams, idempotencyKey?: string): Promise<Contact> {\n const resp = await request<{ data?: Contact }>(baseUrl, \"/api/v1/contacts\", apiKey, {\n method: \"POST\",\n body: contact,\n idempotencyKey,\n });\n return resp.data ?? (resp as unknown as Contact);\n },\n\n /** Update a contact (partial). */\n async update(contactId: number, fields: ContactUpdateParams): Promise<{ updated: number }> {\n return request(baseUrl, `/api/v1/contacts/${contactId}`, apiKey, {\n method: \"PATCH\",\n body: fields,\n });\n },\n\n /** Delete a contact (soft-delete). */\n async delete(contactId: number): Promise<{ deleted: boolean }> {\n return request(baseUrl, `/api/v1/contacts/${contactId}`, apiKey, { method: \"DELETE\" });\n },\n\n /** List custom contact columns. Pass listId to include list-specific columns. */\n async listColumns(listId?: number): Promise<{ data: ContactColumn[] }> {\n return request(baseUrl, \"/api/v1/contacts/columns\", apiKey, {\n query: listId != null ? { list_id: listId } : undefined,\n });\n },\n\n /** Create a custom contact column. Global if list_id is omitted, list-scoped otherwise. */\n async createColumn(params: ContactColumnCreateParams): Promise<ContactColumn> {\n const resp = await request<{ data?: ContactColumn }>(baseUrl, \"/api/v1/contacts/columns/create\", apiKey, {\n method: \"POST\",\n body: {\n title: params.title,\n data_type: params.data_type || \"text\",\n list_id: params.list_id ?? null,\n created_by: params.created_by,\n },\n });\n return resp.data ?? (resp as unknown as ContactColumn);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface Company {\n id: number;\n name: string | null;\n domain: string | null;\n industry: string | null;\n employee_count: number | null;\n revenue: number | null;\n founded_year: number | null;\n description: string | null;\n linkedin_url: string | null;\n country: string | null;\n state: string | null;\n city: string | null;\n}\n\nexport interface CompanyListParams {\n page?: number;\n limit?: number;\n domain?: string;\n industry?: string;\n name?: string;\n country?: string;\n}\n\nexport interface CompanyUpdateParams {\n name?: string;\n domain?: string;\n industry?: string;\n description?: string;\n linkedin_url?: string;\n country?: string;\n state?: string;\n city?: string;\n}\n\nexport interface CompanyContact {\n id: number;\n first_name: string | null;\n last_name: string | null;\n work_email: string | null;\n job_title: string | null;\n}\n\n/** A column definition on companies (base or custom). */\nexport interface CompanyColumn {\n id: number | null;\n title: string;\n data_type: string;\n name: string | null;\n /** Stringified list_id when list-scoped, otherwise null/empty for global. */\n object_id: string | null;\n is_global: boolean;\n}\n\nexport interface CompanyColumnCreateParams {\n title: string;\n /** Email of the user creating the column. Required by the backend (audit). */\n created_by: string;\n /** \"text\" (default) — additional types may be added later. */\n data_type?: string;\n /** If set, the column is list-specific. Omit for org-wide global column. */\n list_id?: number;\n}\n\n/**\n * Companies API - search and manage CRM companies. Requires API key (server-side).\n */\nexport const createCompaniesClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** List companies with optional filters. */\n async list(params: CompanyListParams = {}): Promise<{ data: Company[]; total: number }> {\n return request(baseUrl, \"/api/v1/companies\", apiKey, { query: params as Record<string, unknown> });\n },\n\n /** Get a single company by ID. */\n async get(companyId: number): Promise<Company> {\n const resp = await request<{ data?: Company }>(baseUrl, `/api/v1/companies/${companyId}`, apiKey);\n return resp.data ?? (resp as unknown as Company);\n },\n\n /** Get contacts belonging to a company. */\n async contacts(companyId: number, limit = 50, offset = 0): Promise<{ data: CompanyContact[]; total: number }> {\n return request(baseUrl, `/api/v1/companies/${companyId}/contacts`, apiKey, { query: { limit, offset } });\n },\n\n /** Update a company (partial). */\n async update(companyId: number, fields: CompanyUpdateParams): Promise<{ updated: number }> {\n return request(baseUrl, `/api/v1/companies/${companyId}`, apiKey, { method: \"PATCH\", body: fields });\n },\n\n /** Delete a company (soft-delete). */\n async delete(companyId: number): Promise<{ deleted: boolean }> {\n return request(baseUrl, `/api/v1/companies/${companyId}`, apiKey, { method: \"DELETE\" });\n },\n\n /** List custom company columns. Pass listId to include list-specific columns. */\n async listColumns(listId?: number): Promise<{ data: CompanyColumn[] }> {\n return request(baseUrl, \"/api/v1/companies/columns\", apiKey, {\n query: listId != null ? { list_id: listId } : undefined,\n });\n },\n\n /** Create a custom company column. Global if list_id is omitted, list-scoped otherwise. */\n async createColumn(params: CompanyColumnCreateParams): Promise<CompanyColumn> {\n const resp = await request<{ data?: CompanyColumn }>(baseUrl, \"/api/v1/companies/columns/create\", apiKey, {\n method: \"POST\",\n body: {\n title: params.title,\n data_type: params.data_type || \"text\",\n list_id: params.list_id ?? null,\n created_by: params.created_by,\n },\n });\n return resp.data ?? (resp as unknown as CompanyColumn);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface ContactList {\n id: number;\n title: string;\n type: \"contacts\" | \"companies\";\n contact_count: number | null;\n created_at: string | null;\n}\n\nexport interface ListContact {\n id: number;\n first_name: string | null;\n last_name: string | null;\n work_email: string | null;\n job_title: string | null;\n company_name: string | null;\n}\n\n/**\n * Lists API - manage contact and company lists. Requires API key (server-side).\n */\nexport const createListsClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** List all lists. */\n async list(page = 1, limit = 50): Promise<{ data: ContactList[]; total: number }> {\n return request(baseUrl, \"/api/v1/lists\", apiKey, { query: { page, limit } });\n },\n\n /** Create a new list. */\n async create(title: string, type: \"contacts\" | \"companies\" = \"contacts\"): Promise<ContactList> {\n const resp = await request<{ data?: ContactList }>(baseUrl, \"/api/v1/lists\", apiKey, {\n method: \"POST\",\n body: { title, type },\n });\n return resp.data ?? (resp as unknown as ContactList);\n },\n\n /** Delete a list (soft-delete). */\n async delete(listId: number): Promise<{ deleted: boolean }> {\n return request(baseUrl, `/api/v1/lists/${listId}`, apiKey, { method: \"DELETE\" });\n },\n\n /** Get contacts in a list. */\n async contacts(listId: number, page = 1, limit = 50): Promise<{ data: ListContact[]; total: number }> {\n return request(baseUrl, `/api/v1/lists/${listId}/contacts`, apiKey, { query: { page, limit } });\n },\n\n /** Add contacts to a list. */\n async addContacts(listId: number, contactIds: number[]): Promise<{ added: number }> {\n return request(baseUrl, `/api/v1/lists/${listId}/contacts`, apiKey, {\n method: \"POST\",\n body: { contact_ids: contactIds },\n });\n },\n\n /** Remove contacts from a list. */\n async removeContacts(listId: number, contactIds: number[]): Promise<{ removed: number }> {\n return request(baseUrl, `/api/v1/lists/${listId}/contacts`, apiKey, {\n method: \"DELETE\",\n body: { contact_ids: contactIds },\n });\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface Note {\n id: string;\n entity_type: string;\n entity_id: string;\n content: string;\n created_by: string | null;\n created_by_name: string | null;\n created_at: string | null;\n updated_at: string | null;\n}\n\n/**\n * Notes API - CRUD for notes attached to contacts. Requires API key (server-side).\n *\n * Backed by:\n * GET /api/v1/contacts/{contact_id}/notes\n * POST /api/v1/contacts/{contact_id}/notes\n * PATCH /api/v1/notes/{note_id}\n * DELETE /api/v1/notes/{note_id}\n */\nexport const createNotesClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** List all notes on a contact. */\n async list(contactId: number): Promise<{ data: Note[] }> {\n return request(baseUrl, `/api/v1/contacts/${contactId}/notes`, apiKey);\n },\n\n /** Create a note on a contact. */\n async create(contactId: number, content: string): Promise<Note> {\n const resp = await request<{ data?: Note }>(baseUrl, `/api/v1/contacts/${contactId}/notes`, apiKey, {\n method: \"POST\",\n body: { content },\n });\n return resp.data ?? (resp as unknown as Note);\n },\n\n /** Update a note's content. */\n async update(noteId: string, content: string): Promise<Note> {\n const resp = await request<{ data?: Note }>(baseUrl, `/api/v1/notes/${noteId}`, apiKey, {\n method: \"PATCH\",\n body: { content },\n });\n return resp.data ?? (resp as unknown as Note);\n },\n\n /** Delete a note. */\n async delete(noteId: string): Promise<{ data: { deleted: boolean } }> {\n return request(baseUrl, `/api/v1/notes/${noteId}`, apiKey, { method: \"DELETE\" });\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface Task {\n id: string;\n entity_type: string | null;\n entity_id: string | null;\n title: string;\n description: string | null;\n due_date: string | null;\n assignee_id: string | null;\n assignee_name: string | null;\n /** \"open\" | \"completed\" (other values may appear if the backend adds states later) */\n status: string | null;\n /** 0=none, 1=urgent, 2=high, 3=normal, 4=low */\n priority: number | null;\n task_type: string | null;\n created_by: string | null;\n created_at: string | null;\n updated_at: string | null;\n /** Parent task UUID when this row is a subtask, else null. One level deep. */\n parent_task_id?: string | null;\n /** Sort position within the parent's subtasks. 0 when not a subtask. */\n subtask_sort_order?: number | null;\n /** Number of subtasks under this task (top-level rows only). */\n subtask_count?: number | null;\n /** Subset of subtask_count whose status is \"completed\". */\n completed_subtask_count?: number | null;\n}\n\nexport interface TaskCreateParams {\n title: string;\n description?: string;\n /** ISO 8601 date string. */\n due_date?: string;\n assignee_id?: string;\n /** 0=none, 1=urgent, 2=high, 3=normal, 4=low */\n priority?: number;\n /**\n * When set, the new task is created as a subtask of this parent. Parent\n * must exist and must not itself be a subtask (subtasks are one level\n * deep).\n */\n parent_task_id?: string;\n /**\n * Sort position within the parent's subtasks. Omit to append at the end.\n */\n subtask_sort_order?: number;\n}\n\nexport interface TaskUpdateParams {\n title?: string;\n description?: string;\n due_date?: string;\n assignee_id?: string;\n /** \"open\" | \"completed\" */\n status?: string;\n priority?: number;\n /**\n * Re-parent this task into a subtask of the given parent. Parent must\n * exist, must not itself be a subtask, and a task that already has\n * subtasks of its own cannot be demoted into a subtask.\n */\n parent_task_id?: string;\n /** Reorder within the parent's subtasks. Can be sent alone. */\n subtask_sort_order?: number;\n}\n\nexport interface TaskListParams {\n /** \"open\" | \"completed\" */\n status?: string;\n /** 0-4 */\n priority?: number;\n assignee_id?: string;\n /** Substring search on title. */\n search?: string;\n}\n\n/**\n * Tasks API - CRUD for tasks attached to contacts. Requires API key (server-side).\n *\n * Backed by:\n * GET /api/v1/contacts/{contact_id}/tasks\n * GET /api/v1/tasks\n * POST /api/v1/contacts/{contact_id}/tasks\n * PATCH /api/v1/tasks/{task_id}\n * DELETE /api/v1/tasks/{task_id}\n */\nexport const createTasksClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** List tasks on a single contact. Optional status filter (\"open\" | \"completed\"). */\n async listForContact(contactId: number, status?: string): Promise<{ data: Task[] }> {\n return request(baseUrl, `/api/v1/contacts/${contactId}/tasks`, apiKey, {\n query: status ? { status } : undefined,\n });\n },\n\n /** List all tasks org-wide with optional filters. */\n async list(params: TaskListParams = {}): Promise<{ data: Task[] }> {\n return request(baseUrl, \"/api/v1/tasks\", apiKey, { query: params as Record<string, unknown> });\n },\n\n /** Create a task on a contact. */\n async create(contactId: number, task: TaskCreateParams): Promise<Task> {\n const resp = await request<{ data?: Task }>(baseUrl, `/api/v1/contacts/${contactId}/tasks`, apiKey, {\n method: \"POST\",\n body: task,\n });\n return resp.data ?? (resp as unknown as Task);\n },\n\n /** Update a task (partial). */\n async update(taskId: string, fields: TaskUpdateParams): Promise<Task> {\n const resp = await request<{ data?: Task }>(baseUrl, `/api/v1/tasks/${taskId}`, apiKey, {\n method: \"PATCH\",\n body: fields,\n });\n return resp.data ?? (resp as unknown as Task);\n },\n\n /** Delete a task. */\n async delete(taskId: string): Promise<{ data: { deleted: boolean } }> {\n return request(baseUrl, `/api/v1/tasks/${taskId}`, apiKey, { method: \"DELETE\" });\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\n/** A field (column) definition on contacts or companies — base or custom. */\nexport interface Field {\n id: number | null;\n title: string;\n /** Internal column name (slug). */\n name: string | null;\n /** Currently only \"text\" is supported; other types may be added later. */\n data_type: string;\n /** True if available org-wide, false if list-specific. */\n is_global: boolean;\n}\n\n/** Created custom field (column). */\nexport interface CreatedField {\n id: number;\n title: string;\n data_type: string;\n name: string;\n list_id: number | null;\n is_global: boolean;\n}\n\nexport interface FieldCreateParams {\n title: string;\n /** \"contacts\" or \"companies\". Defaults to \"contacts\" on the backend. */\n entity?: \"contacts\" | \"companies\";\n /** \"text\" (default) — additional types may be added later. */\n data_type?: string;\n /** If set, the field is list-specific. Omit for org-wide global field. */\n list_id?: number;\n}\n\nexport interface FieldDeleteParams {\n entity?: \"contacts\" | \"companies\";\n /**\n * Optional list scope guard. If provided, the column must belong to this\n * list or the request returns 404. Use this to prevent accidentally\n * deleting a column on a different list in the same org.\n */\n list_id?: number;\n}\n\nexport interface SetFieldValueParams {\n /** Contact ID (entity='contacts') or company ID (entity='companies'). */\n record_id: number;\n /** Value to write. Pass null/undefined to clear the field. */\n value?: string | null;\n entity?: \"contacts\" | \"companies\";\n}\n\n/**\n * Fields API - manage custom fields (columns) on contacts and companies.\n * Requires API key (server-side). On the hardened HTTP core: throws a typed\n * `G8Error` on failure and retries transient errors.\n *\n * Backed by:\n * GET /api/v1/fields — list contact fields\n * GET /api/v1/fields/companies — list company fields\n * POST /api/v1/fields — create a custom field\n * DELETE /api/v1/fields/{column_id} — delete a custom field\n * PATCH /api/v1/fields/{column_id}/values — set value on a single record\n */\nexport const createFieldsClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** List contact fields (base + custom). Pass listId to include list-specific custom fields. */\n async listContactFields(listId?: number): Promise<{ data: Field[] }> {\n return request(baseUrl, \"/api/v1/fields\", apiKey, { query: listId != null ? { list_id: listId } : undefined });\n },\n\n /** List company fields (base + custom). Pass listId to include list-specific custom fields. */\n async listCompanyFields(listId?: number): Promise<{ data: Field[] }> {\n return request(baseUrl, \"/api/v1/fields/companies\", apiKey, {\n query: listId != null ? { list_id: listId } : undefined,\n });\n },\n\n /** Create a custom field on contacts (default) or companies. */\n async create(params: FieldCreateParams): Promise<CreatedField> {\n const resp = await request<{ data?: CreatedField }>(baseUrl, \"/api/v1/fields\", apiKey, {\n method: \"POST\",\n body: {\n title: params.title,\n data_type: params.data_type || \"text\",\n list_id: params.list_id ?? null,\n entity: params.entity || \"contacts\",\n },\n });\n return resp.data ?? (resp as unknown as CreatedField);\n },\n\n /** Delete a custom field (soft-delete). Pass list_id to scope-guard against cross-list deletion. */\n async delete(\n columnId: number,\n params: FieldDeleteParams = {},\n ): Promise<{ data: { column_id: number; deleted: boolean } }> {\n const query: Record<string, unknown> = { entity: params.entity || \"contacts\" };\n if (params.list_id != null) query.list_id = params.list_id;\n return request(baseUrl, `/api/v1/fields/${columnId}`, apiKey, { method: \"DELETE\", query });\n },\n\n /** Set a custom field value on a single contact or company row. Pass value=null to clear. */\n async setValue(\n columnId: number,\n params: SetFieldValueParams,\n ): Promise<{ data: { column_id: number; record_id: number; updated: boolean } }> {\n return request(baseUrl, `/api/v1/fields/${columnId}/values`, apiKey, {\n method: \"PATCH\",\n body: { record_id: params.record_id, value: params.value ?? null, entity: params.entity || \"contacts\" },\n });\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface Deal {\n id: string | null;\n name: string | null;\n description: string | null;\n amount: number | null;\n currency: string | null;\n stage_id: string | null;\n stage_name: string | null;\n pipeline_id: string | null;\n /** Linked company ID (mashup_company_id), if any. */\n company_id: number | string | null;\n owner_id: string | null;\n /** ISO 8601 date. */\n close_date: string | null;\n created_at: string | null;\n updated_at: string | null;\n}\n\nexport interface DealCreateParams {\n name: string;\n /**\n * Deal owner (user id or email). Required.\n */\n owner_id: string;\n /**\n * mashup_contact_ids to attach. Required, at least one. Every contact must\n * belong to the same company, and that company becomes the deal's company.\n * Same id space as the contacts API. Attach is idempotent.\n */\n contact_ids: number[];\n /**\n * Deprecated: the company is derived from `contact_ids`. If supplied it must\n * match the contacts' company, otherwise omit it.\n */\n company_id?: number;\n description?: string;\n amount?: number;\n /** Default: \"USD\". */\n currency?: string;\n /** Stage ID from the org's pipelines. Defaults to first stage of default pipeline if omitted. */\n stage_id?: string;\n /** Pipeline ID. Defaults to org's default pipeline if omitted. */\n pipeline_id?: string;\n /** ISO 8601 close date. */\n close_date?: string;\n /**\n * Set true to create a deal even if one already exists for the company.\n * By default the API rejects a duplicate with HTTP 409.\n */\n allow_duplicate?: boolean;\n}\n\nexport interface DealUpdateParams {\n name?: string;\n description?: string;\n amount?: number;\n currency?: string;\n stage_id?: string;\n /** ISO 8601 close date. */\n close_date?: string;\n /** Reassign the deal owner (user id or email). Pass null to clear. */\n owner_id?: string | null;\n /**\n * mashup_contact_ids to link. Must belong to the deal's company (if the deal\n * has none yet, the added contacts' company is adopted); a cross-company add\n * is rejected. Idempotent.\n */\n add_contact_ids?: number[];\n /** mashup_contact_ids to unlink. Idempotent. */\n remove_contact_ids?: number[];\n}\n\nexport interface DealListParams {\n page?: number;\n limit?: number;\n stage_id?: string;\n pipeline_id?: string;\n /** Substring search on deal name. */\n search?: string;\n}\n\nexport interface PipelineStage {\n id: string;\n name: string;\n probability: number | null;\n position: number | null;\n stage_type: string | null;\n color: string | null;\n required_elements: string[];\n recommended_elements: string[];\n channel_scripts: Record<string, string>;\n}\n\nexport interface Pipeline {\n id: string;\n name: string;\n is_default: boolean;\n stages: PipelineStage[];\n}\n\n/** Trimmed deal shape returned by /contacts/{id}/deals and /companies/{id}/deals. */\nexport interface ContactDeal {\n deal_id: string | null;\n name: string | null;\n stage: string | null;\n value: number | null;\n currency: string | null;\n role: string | null;\n pipeline_id: string | null;\n close_date: string | null;\n owner_id: string | null;\n created_at: string | null;\n}\n\nexport interface PaginationMeta {\n page: number;\n limit: number;\n total: number;\n has_next: boolean;\n}\n\n/**\n * Deals API - CRUD for deals + pipelines. Requires API key (server-side).\n *\n * Backed by:\n * GET /api/v1/deals/pipelines\n * GET /api/v1/deals\n * POST /api/v1/deals\n * GET /api/v1/deals/{deal_id}\n * PATCH /api/v1/deals/{deal_id}\n * DELETE /api/v1/deals/{deal_id}\n * GET /api/v1/contacts/{contact_id}/deals\n * GET /api/v1/companies/{company_id}/deals\n */\nexport const createDealsClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** List all deal pipelines and their stages. */\n async pipelines(): Promise<{ data: Pipeline[] }> {\n return request(baseUrl, \"/api/v1/deals/pipelines\", apiKey);\n },\n\n /** List deals org-wide with optional filters and pagination. */\n async list(params: DealListParams = {}): Promise<{ data: Deal[]; pagination?: PaginationMeta }> {\n return request(baseUrl, \"/api/v1/deals\", apiKey, { query: params as Record<string, unknown> });\n },\n\n /** Create a new deal. */\n async create(deal: DealCreateParams): Promise<Deal> {\n const resp = await request<{ data?: Deal }>(baseUrl, \"/api/v1/deals\", apiKey, { method: \"POST\", body: deal });\n return resp.data ?? (resp as unknown as Deal);\n },\n\n /** Get a single deal by ID. */\n async get(dealId: string): Promise<Deal> {\n const resp = await request<{ data?: Deal }>(baseUrl, `/api/v1/deals/${dealId}`, apiKey);\n return resp.data ?? (resp as unknown as Deal);\n },\n\n /** Update a deal (partial). */\n async update(dealId: string, fields: DealUpdateParams): Promise<Deal> {\n const resp = await request<{ data?: Deal }>(baseUrl, `/api/v1/deals/${dealId}`, apiKey, {\n method: \"PATCH\",\n body: fields,\n });\n return resp.data ?? (resp as unknown as Deal);\n },\n\n /** Delete a deal. */\n async delete(dealId: string): Promise<{ data: { deleted: boolean } }> {\n return request(baseUrl, `/api/v1/deals/${dealId}`, apiKey, { method: \"DELETE\" });\n },\n\n /** Get all deals associated with a contact. */\n async forContact(contactId: number): Promise<{ data: ContactDeal[] }> {\n return request(baseUrl, `/api/v1/contacts/${contactId}/deals`, apiKey);\n },\n\n /** Get all deals associated with a company. */\n async forCompany(companyId: number): Promise<{ data: ContactDeal[] }> {\n return request(baseUrl, `/api/v1/companies/${companyId}/deals`, apiKey);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\n/**\n * Inbox channel — `email`, `sms`, or `linkedin` (HeyReach internally).\n * Defaults to `email` on routes that accept this as a query param.\n */\nexport type InboxChannel = \"email\" | \"sms\" | \"linkedin\";\n\nexport interface InboxContact {\n name?: string | null;\n email?: string | null;\n company?: string | null;\n [key: string]: unknown;\n}\n\nexport interface InboxTag {\n id: string;\n name: string;\n}\n\nexport interface InboxAssignee {\n email: string;\n name?: string | null;\n [key: string]: unknown;\n}\n\nexport interface InboxMessage {\n message_id: string | null;\n from_address: string | null;\n to_addresses: string[];\n content: string | null;\n /** \"USER\", \"AI\", or \"OTHER\". */\n responder: string | null;\n date: string | null;\n is_draft: boolean;\n}\n\nexport interface InboxThread {\n id: string;\n /** \"email\", \"sms\", or \"linkedin\". */\n channel: string;\n subject: string | null;\n contact: InboxContact | null;\n messages: InboxMessage[];\n /** \"open\", \"responded\", \"ai_responded\", etc. */\n status: string | null;\n tags: InboxTag[];\n assignees: InboxAssignee[];\n created_at: string | null;\n updated_at: string | null;\n}\n\nexport interface InboxListParams {\n channel?: InboxChannel;\n sequence_id?: string;\n /** Filter by thread status (e.g. \"open\", \"responded\", \"ai_responded\"). */\n status?: string;\n /** Filter by assignee email. */\n assignee?: string;\n /** Filter by tag ID. */\n tag?: string;\n page?: number;\n /** Default 50, max 100. */\n page_size?: number;\n}\n\nexport interface InboxAssignResult {\n assigned: boolean;\n assignee: string;\n count: number;\n [key: string]: unknown;\n}\n\nexport interface InboxTagResult {\n tagged: boolean;\n tag_count: number;\n [key: string]: unknown;\n}\n\nexport interface InboxDraft {\n /** HTML body. */\n content: string;\n /** Plain-text alternative, if available. */\n plain_content: string | null;\n /** Credits charged for AI generation. */\n credits_charged: number;\n}\n\nexport interface InboxSendParams {\n body: string;\n channel: InboxChannel;\n subject?: string;\n /** Recipient override — email, phone, or LinkedIn ID. */\n to?: string;\n /** Sender override — mailbox email, Twilio number, or LinkedIn account ID. */\n from_address?: string;\n}\n\nexport interface InboxSendResult {\n message_id: string | null;\n status: string;\n channel: string;\n}\n\n/**\n * Inbox API — read + reply to multi-channel inbox threads (email, SMS, LinkedIn/HeyReach).\n * Requires API key (server-side). On the hardened HTTP core: throws a typed\n * `G8Error` on failure (e.g. 402 when an AI draft exceeds your credit balance)\n * and retries transient errors.\n *\n * Backed by:\n * GET /api/v1/inbox\n * GET /api/v1/inbox/{reply_id}\n * POST /api/v1/inbox/{reply_id}/assign\n * POST /api/v1/inbox/{reply_id}/tag\n * GET /api/v1/inbox/{reply_id}/draft (charges credits, 402 on insufficient balance)\n * POST /api/v1/inbox/{reply_id}/send\n */\nexport const createInboxClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** List inbox threads across email, SMS, and LinkedIn. */\n async list(params: InboxListParams = {}): Promise<{ data: InboxThread[] }> {\n return request(baseUrl, \"/api/v1/inbox\", apiKey, { query: params as Record<string, unknown> });\n },\n\n /** Get a single inbox thread. Defaults to email channel. */\n async get(replyId: string, channel: InboxChannel = \"email\"): Promise<InboxThread> {\n const resp = await request<{ data?: InboxThread }>(baseUrl, `/api/v1/inbox/${replyId}`, apiKey, {\n query: { channel },\n });\n return resp.data ?? (resp as unknown as InboxThread);\n },\n\n /** Assign a user to an inbox thread. */\n async assign(replyId: string, assigneeEmail: string, channel: InboxChannel = \"email\"): Promise<InboxAssignResult> {\n const resp = await request<{ data?: InboxAssignResult }>(baseUrl, `/api/v1/inbox/${replyId}/assign`, apiKey, {\n method: \"POST\",\n query: { channel },\n body: { assignee_email: assigneeEmail },\n });\n return resp.data ?? (resp as unknown as InboxAssignResult);\n },\n\n /** Attach tag IDs to an inbox thread. */\n async tag(replyId: string, tagIds: string[], channel: InboxChannel = \"email\"): Promise<InboxTagResult> {\n const resp = await request<{ data?: InboxTagResult }>(baseUrl, `/api/v1/inbox/${replyId}/tag`, apiKey, {\n method: \"POST\",\n query: { channel },\n body: { tag_ids: tagIds },\n });\n return resp.data ?? (resp as unknown as InboxTagResult);\n },\n\n /**\n * Generate an AI draft reply for a thread.\n * Charges credits — server returns 402 if balance is insufficient.\n */\n async draft(replyId: string, channel: InboxChannel = \"email\"): Promise<InboxDraft> {\n const resp = await request<{ data?: InboxDraft }>(baseUrl, `/api/v1/inbox/${replyId}/draft`, apiKey, {\n query: { channel },\n });\n return resp.data ?? (resp as unknown as InboxDraft);\n },\n\n /** Send a reply through email, SMS, or LinkedIn. */\n async send(replyId: string, payload: InboxSendParams): Promise<InboxSendResult> {\n const resp = await request<{ data?: InboxSendResult }>(baseUrl, `/api/v1/inbox/${replyId}/send`, apiKey, {\n method: \"POST\",\n body: payload,\n });\n return resp.data ?? (resp as unknown as InboxSendResult);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface QuoteLineItem {\n product_id?: string | null;\n name?: string | null;\n description?: string | null;\n quantity: number;\n unit_price: number;\n currency?: string | null;\n recurring?: boolean | null;\n}\n\nexport type QuoteStatus = \"draft\" | \"sent\" | \"signed\" | \"declined\" | \"expired\" | \"void\";\n\nexport interface QuoteSummary {\n id: string;\n name: string | null;\n status: QuoteStatus;\n total: number | null;\n currency: string | null;\n contact_id: number | null;\n company_id: number | null;\n expires_at: string | null;\n created_at: string | null;\n updated_at: string | null;\n signing_url: string | null;\n payment_link_url: string | null;\n}\n\nexport interface QuoteDetail extends QuoteSummary {\n line_items: QuoteLineItem[];\n notes: string | null;\n recipient_email: string | null;\n signed_at: string | null;\n sent_at: string | null;\n}\n\nexport interface QuoteCreateParams {\n contact_id?: number;\n company_id?: number;\n line_items: QuoteLineItem[];\n currency?: string;\n notes?: string;\n /** ISO 8601 timestamp. */\n expires_at?: string;\n name?: string;\n}\n\nexport interface QuoteUpdateParams {\n line_items?: QuoteLineItem[];\n notes?: string;\n expires_at?: string;\n name?: string;\n}\n\nexport interface QuoteSendParams {\n recipient_email: string;\n /** Whether to attach the signing link. Defaults to true. */\n send_signing_link?: boolean;\n}\n\nexport interface QuoteListParams {\n status?: QuoteStatus;\n contact_id?: number;\n company_id?: number;\n page?: number;\n limit?: number;\n}\n\nexport interface QuotableProduct {\n id: string;\n name: string;\n description: string | null;\n unit_price: number;\n currency: string;\n recurring: boolean;\n}\n\nexport interface QuoteSettings {\n default_currency: string;\n default_tax_rate: number | null;\n payment_providers: string[];\n logo_url: string | null;\n signature_required: boolean;\n}\n\nexport interface PaginationMeta {\n page: number;\n limit: number;\n total: number;\n has_next: boolean;\n}\n\n/**\n * Quotes API - quote-to-cash lifecycle. Requires API key (server-side). On the\n * hardened HTTP core: throws a typed `G8Error` on failure and retries transient\n * errors.\n *\n * Backed by:\n * GET /api/v1/quotes\n * GET /api/v1/quotes/{id}\n * POST /api/v1/quotes\n * PUT /api/v1/quotes/{id}\n * DELETE /api/v1/quotes/{id}\n * POST /api/v1/quotes/{id}/duplicate\n * POST /api/v1/quotes/{id}/edit-as-draft\n * POST /api/v1/quotes/{id}/send\n * GET /api/v1/quotable-products\n * GET /api/v1/quote-settings\n * GET /api/v1/contacts/{contact_id}/quotes\n * GET /api/v1/companies/{company_id}/quotes\n */\nexport const createQuotesClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** List quotes org-wide with optional filters and pagination. */\n async list(params: QuoteListParams = {}): Promise<{ data: QuoteSummary[]; pagination?: PaginationMeta }> {\n return request(baseUrl, \"/api/v1/quotes\", apiKey, { query: params as Record<string, unknown> });\n },\n\n /** Get full details for a single quote. */\n async get(quoteId: string): Promise<QuoteDetail> {\n const resp = await request<{ data?: QuoteDetail }>(baseUrl, `/api/v1/quotes/${quoteId}`, apiKey);\n return resp.data ?? (resp as unknown as QuoteDetail);\n },\n\n /** Create a new quote from line items. */\n async create(quote: QuoteCreateParams): Promise<QuoteDetail> {\n const resp = await request<{ data?: QuoteDetail }>(baseUrl, \"/api/v1/quotes\", apiKey, {\n method: \"POST\",\n body: quote,\n });\n return resp.data ?? (resp as unknown as QuoteDetail);\n },\n\n /** Update a draft quote (line items, expiry, notes). */\n async update(quoteId: string, fields: QuoteUpdateParams): Promise<QuoteDetail> {\n const resp = await request<{ data?: QuoteDetail }>(baseUrl, `/api/v1/quotes/${quoteId}`, apiKey, {\n method: \"PUT\",\n body: fields,\n });\n return resp.data ?? (resp as unknown as QuoteDetail);\n },\n\n /** Delete a draft quote (irreversible). */\n async delete(quoteId: string): Promise<{ data: { deleted: boolean } }> {\n return request(baseUrl, `/api/v1/quotes/${quoteId}`, apiKey, { method: \"DELETE\" });\n },\n\n /** Duplicate an existing quote (all line items copied into a new draft). */\n async duplicate(quoteId: string): Promise<QuoteDetail> {\n const resp = await request<{ data?: QuoteDetail }>(baseUrl, `/api/v1/quotes/${quoteId}/duplicate`, apiKey, {\n method: \"POST\",\n body: {},\n });\n return resp.data ?? (resp as unknown as QuoteDetail);\n },\n\n /** Convert a signed / sent quote back to editable draft state. */\n async editAsDraft(quoteId: string): Promise<{ data: { id: string; status: string } }> {\n return request(baseUrl, `/api/v1/quotes/${quoteId}/edit-as-draft`, apiKey, { method: \"POST\", body: {} });\n },\n\n /** Send a quote to its recipient via email (with signature + optional payment link). */\n async send(quoteId: string, params: QuoteSendParams): Promise<QuoteDetail> {\n const resp = await request<{ data?: QuoteDetail }>(baseUrl, `/api/v1/quotes/${quoteId}/send`, apiKey, {\n method: \"POST\",\n body: params,\n });\n return resp.data ?? (resp as unknown as QuoteDetail);\n },\n\n /** List products available for line items. */\n async products(): Promise<{ data: QuotableProduct[] }> {\n return request(baseUrl, \"/api/v1/quotable-products\", apiKey);\n },\n\n /** Get org-level quote settings (currency, tax rate, payment providers, logo). */\n async settings(): Promise<QuoteSettings> {\n const resp = await request<{ data?: QuoteSettings }>(baseUrl, \"/api/v1/quote-settings\", apiKey);\n return resp.data ?? (resp as unknown as QuoteSettings);\n },\n\n /** Get all quotes associated with a contact. */\n async forContact(contactId: number): Promise<{ data: QuoteSummary[] }> {\n return request(baseUrl, `/api/v1/contacts/${contactId}/quotes`, apiKey);\n },\n\n /** Get all quotes associated with a company. */\n async forCompany(companyId: number): Promise<{ data: QuoteSummary[] }> {\n return request(baseUrl, `/api/v1/companies/${companyId}/quotes`, apiKey);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\n/**\n * Stage Checklist v2 pipelines. A \"pipeline\" here is a multi-stage workflow\n * (with evidence requirements and per-channel scripts) that lives parallel\n * to deal pipelines. Use `g8.deals.pipelines()` for deal-pipeline reads.\n */\nexport interface StagePipelineStage {\n id: string;\n name: string;\n position: number;\n /** Evidence keys that must be collected before the stage can be marked done. */\n required_elements: string[];\n /** Evidence keys that are recommended but not enforced. */\n recommended_elements: string[];\n /** Channel-specific scripts (call, email, linkedin, etc.). */\n channel_scripts: Record<string, string>;\n color: string | null;\n stage_type: string | null;\n}\n\nexport interface StagePipeline {\n id: string;\n name: string;\n target: string | null;\n is_default: boolean;\n stages: StagePipelineStage[];\n created_at: string | null;\n updated_at: string | null;\n}\n\nexport interface StagePipelineCreateParams {\n name: string;\n target?: string;\n /** If true, creates an empty pipeline (no default stages). */\n blank?: boolean;\n}\n\nexport interface StagePipelineUpdateParams {\n name?: string;\n target?: string;\n}\n\nexport interface StageCreateParams {\n name: string;\n position?: number;\n required_elements?: string[];\n recommended_elements?: string[];\n channel_scripts?: Record<string, string>;\n color?: string;\n stage_type?: string;\n}\n\nexport interface StageUpdateParams {\n name?: string;\n position?: number;\n required_elements?: string[];\n recommended_elements?: string[];\n channel_scripts?: Record<string, string>;\n color?: string;\n}\n\nexport interface EvidenceKey {\n key: string;\n label: string;\n description: string;\n category: string;\n}\n\nexport interface PipelineSuggestion {\n suggestion_id: string;\n name: string;\n target: string;\n stages: Array<{ name: string; required_elements: string[]; channel_scripts: Record<string, string> }>;\n rationale: string;\n}\n\n/**\n * Stage Checklist Pipelines API - workflow pipelines with evidence + scripts.\n * Requires API key (server-side). On the hardened HTTP core: throws a typed\n * `G8Error` on failure and retries transient errors.\n *\n * Backed by:\n * GET /api/v1/pipelines\n * GET /api/v1/pipelines/{id}\n * GET /api/v1/pipelines/evidence-library\n * POST /api/v1/pipelines\n * PUT /api/v1/pipelines/{id}\n * DELETE /api/v1/pipelines/{id}\n * POST /api/v1/pipelines/{id}/stages\n * PUT /api/v1/pipelines/{id}/stages/{stage_id}\n * DELETE /api/v1/pipelines/{id}/stages/{stage_id}\n * PUT /api/v1/pipelines/{id}/stages/reorder\n * POST /api/v1/pipelines/suggest\n * POST /api/v1/pipelines/from-suggestion\n */\nexport const createPipelinesClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** List all stage-checklist pipelines with stages, evidence, scripts. */\n async list(): Promise<{ data: StagePipeline[] }> {\n return request(baseUrl, \"/api/v1/pipelines\", apiKey);\n },\n\n /** Get a single pipeline by ID. */\n async get(pipelineId: string): Promise<StagePipeline> {\n const resp = await request<{ data?: StagePipeline }>(baseUrl, `/api/v1/pipelines/${pipelineId}`, apiKey);\n return resp.data ?? (resp as unknown as StagePipeline);\n },\n\n /** Get the canonical evidence-key library (used when defining stages). */\n async evidenceLibrary(): Promise<{ data: EvidenceKey[] }> {\n return request(baseUrl, \"/api/v1/pipelines/evidence-library\", apiKey);\n },\n\n /** Create a new pipeline. Defaults to a templated set of stages; pass blank=true for empty. */\n async create(params: StagePipelineCreateParams): Promise<StagePipeline> {\n const resp = await request<{ data?: StagePipeline }>(baseUrl, \"/api/v1/pipelines\", apiKey, {\n method: \"POST\",\n body: params,\n });\n return resp.data ?? (resp as unknown as StagePipeline);\n },\n\n /** Update pipeline metadata (name, target). */\n async update(pipelineId: string, fields: StagePipelineUpdateParams): Promise<StagePipeline> {\n const resp = await request<{ data?: StagePipeline }>(baseUrl, `/api/v1/pipelines/${pipelineId}`, apiKey, {\n method: \"PUT\",\n body: fields,\n });\n return resp.data ?? (resp as unknown as StagePipeline);\n },\n\n /** Delete a pipeline. Only allowed when no deals reference it. */\n async delete(pipelineId: string): Promise<{ data: { deleted: boolean } }> {\n return request(baseUrl, `/api/v1/pipelines/${pipelineId}`, apiKey, { method: \"DELETE\" });\n },\n\n /** Add a new stage to a pipeline. */\n async createStage(pipelineId: string, stage: StageCreateParams): Promise<StagePipelineStage> {\n const resp = await request<{ data?: StagePipelineStage }>(\n baseUrl,\n `/api/v1/pipelines/${pipelineId}/stages`,\n apiKey,\n { method: \"POST\", body: stage },\n );\n return resp.data ?? (resp as unknown as StagePipelineStage);\n },\n\n /** Update a stage (evidence, scripts, position). */\n async updateStage(pipelineId: string, stageId: string, fields: StageUpdateParams): Promise<StagePipelineStage> {\n const resp = await request<{ data?: StagePipelineStage }>(\n baseUrl,\n `/api/v1/pipelines/${pipelineId}/stages/${stageId}`,\n apiKey,\n { method: \"PUT\", body: fields },\n );\n return resp.data ?? (resp as unknown as StagePipelineStage);\n },\n\n /** Reorder stages within a pipeline (pass full ordered list of stage IDs). */\n async reorderStages(pipelineId: string, stageIds: string[]): Promise<{ data: StagePipelineStage[] }> {\n return request(baseUrl, `/api/v1/pipelines/${pipelineId}/stages/reorder`, apiKey, {\n method: \"PUT\",\n body: { stage_ids: stageIds },\n });\n },\n\n /** Delete a stage from a pipeline. */\n async deleteStage(pipelineId: string, stageId: string): Promise<{ data: { deleted: boolean } }> {\n return request(baseUrl, `/api/v1/pipelines/${pipelineId}/stages/${stageId}`, apiKey, { method: \"DELETE\" });\n },\n\n /** Get an AI-suggested pipeline based on org context (brand, ICP, messaging). */\n async suggest(): Promise<{ data: PipelineSuggestion }> {\n return request(baseUrl, \"/api/v1/pipelines/suggest\", apiKey, { method: \"POST\", body: {} });\n },\n\n /** Create a real pipeline from an AI suggestion (optionally with overrides). */\n async fromSuggestion(\n suggestionId: string,\n overrides?: Partial<{ name: string; target: string }>,\n ): Promise<StagePipeline> {\n const resp = await request<{ data?: StagePipeline }>(baseUrl, \"/api/v1/pipelines/from-suggestion\", apiKey, {\n method: \"POST\",\n body: { suggestion_id: suggestionId, ...(overrides || {}) },\n });\n return resp.data ?? (resp as unknown as StagePipeline);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface WorkflowNode {\n id: string;\n type: string;\n config: Record<string, unknown>;\n position?: { x: number; y: number };\n /** Mapping from this node's output to the next node's input. */\n input_mappings?: Record<string, string>;\n}\n\nexport interface WorkflowConnection {\n from_node_id: string;\n to_node_id: string;\n condition?: string | null;\n}\n\nexport interface WorkflowConfig {\n nodes: WorkflowNode[];\n connections: WorkflowConnection[];\n trigger?: Record<string, unknown> | null;\n}\n\nexport interface Workflow {\n id: string;\n name: string;\n description: string | null;\n config: WorkflowConfig;\n trigger_config: Record<string, unknown> | null;\n is_active: boolean;\n created_at: string | null;\n updated_at: string | null;\n}\n\nexport interface WorkflowCreateParams {\n name: string;\n description?: string;\n config?: WorkflowConfig;\n trigger_config?: Record<string, unknown>;\n}\n\nexport interface WorkflowUpdateParams {\n name?: string;\n description?: string;\n config?: WorkflowConfig;\n trigger_config?: Record<string, unknown>;\n is_active?: boolean;\n}\n\nexport interface WorkflowExecution {\n id: string;\n workflow_id: string;\n status: \"pending\" | \"running\" | \"paused\" | \"completed\" | \"failed\" | \"stopped\";\n trigger_payload: Record<string, unknown>;\n outputs: Record<string, unknown>;\n error: string | null;\n started_at: string | null;\n ended_at: string | null;\n}\n\nexport interface NodeTypeSchema {\n type: string;\n label: string;\n description: string;\n config_schema: Record<string, unknown>;\n output_schema: Record<string, unknown>;\n}\n\nexport interface WorkflowListParams {\n page?: number;\n limit?: number;\n is_active?: boolean;\n search?: string;\n}\n\n/**\n * Workflows API - automation workflows with nodes, connections, and execution lifecycle.\n * Requires API key (server-side). On the hardened HTTP core: throws a typed\n * `G8Error` on failure and retries transient errors.\n *\n * The graph8 workflow surface treats the whole workflow definition as a single\n * record updated via `update()` — there are no per-node CRUD endpoints. To edit\n * nodes or connections, fetch the workflow, mutate `config.nodes` / `config.connections`,\n * and PUT it back.\n *\n * Backed by:\n * GET /api/v1/workflows\n * GET /api/v1/workflows/{id}\n * POST /api/v1/workflows\n * PUT /api/v1/workflows/{id}\n * DELETE /api/v1/workflows/{id}\n * POST /api/v1/workflows/validate\n * POST /api/v1/workflows/{id}/execute\n * GET /api/v1/workflows/executions/{exec_id}\n * POST /api/v1/workflows/executions/{exec_id}/pause\n * POST /api/v1/workflows/executions/{exec_id}/resume\n * POST /api/v1/workflows/executions/{exec_id}/stop\n * GET /api/v1/workflows/{id}/trigger-status\n * POST /api/v1/workflows/{id}/trigger-reset\n * GET /api/v1/workflows/node-types/schema\n * GET /api/v1/workflows/integrations/slack/users|channels\n * GET /api/v1/workflows/integrations/roam/users|groups\n * GET /api/v1/workflows/mcp-servers\n * GET /api/v1/workflows/dispositions\n * GET /api/v1/workflows/forms/{form_id}/fields\n */\nexport const createWorkflowsClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** List workflows org-wide. */\n async list(params: WorkflowListParams = {}): Promise<{ data: Workflow[] }> {\n return request(baseUrl, \"/api/v1/workflows\", apiKey, { query: params as Record<string, unknown> });\n },\n\n /** Get full workflow definition (nodes, connections, trigger, execution state). */\n async get(workflowId: string): Promise<Workflow> {\n const resp = await request<{ data?: Workflow }>(baseUrl, `/api/v1/workflows/${workflowId}`, apiKey);\n return resp.data ?? (resp as unknown as Workflow);\n },\n\n /** Create a new workflow. */\n async create(params: WorkflowCreateParams): Promise<Workflow> {\n const resp = await request<{ data?: Workflow }>(baseUrl, \"/api/v1/workflows\", apiKey, {\n method: \"POST\",\n body: params,\n });\n return resp.data ?? (resp as unknown as Workflow);\n },\n\n /**\n * Update a workflow. Pass the full `config` (nodes + connections) to edit\n * the graph — node-level CRUD is performed client-side by mutating the\n * config and submitting the updated record.\n */\n async update(workflowId: string, fields: WorkflowUpdateParams): Promise<Workflow> {\n const resp = await request<{ data?: Workflow }>(baseUrl, `/api/v1/workflows/${workflowId}`, apiKey, {\n method: \"PUT\",\n body: fields,\n });\n return resp.data ?? (resp as unknown as Workflow);\n },\n\n /** Delete a workflow. */\n async delete(workflowId: string): Promise<{ data: { deleted: boolean } }> {\n return request(baseUrl, `/api/v1/workflows/${workflowId}`, apiKey, { method: \"DELETE\" });\n },\n\n /** Validate a workflow definition (orphans, dangling connections, required fields). */\n async validate(workflow: { config: WorkflowConfig; trigger_config?: Record<string, unknown> }): Promise<{\n data: { valid: boolean; errors: Array<{ node_id?: string; field?: string; message: string }> };\n }> {\n return request(baseUrl, \"/api/v1/workflows/validate\", apiKey, { method: \"POST\", body: workflow });\n },\n\n /** Execute a workflow immediately with a trigger payload. */\n async execute(workflowId: string, triggerPayload: Record<string, unknown> = {}): Promise<WorkflowExecution> {\n const resp = await request<{ data?: WorkflowExecution }>(\n baseUrl,\n `/api/v1/workflows/${workflowId}/execute`,\n apiKey,\n { method: \"POST\", body: { trigger_payload: triggerPayload } },\n );\n return resp.data ?? (resp as unknown as WorkflowExecution);\n },\n\n /** Get the status + outputs of a single execution. */\n async getExecution(executionId: string): Promise<WorkflowExecution> {\n const resp = await request<{ data?: WorkflowExecution }>(\n baseUrl,\n `/api/v1/workflows/executions/${executionId}`,\n apiKey,\n );\n return resp.data ?? (resp as unknown as WorkflowExecution);\n },\n\n /** Pause a running execution. */\n async pauseExecution(executionId: string): Promise<{ data: { paused: boolean } }> {\n return request(baseUrl, `/api/v1/workflows/executions/${executionId}/pause`, apiKey, { method: \"POST\" });\n },\n\n /** Resume a paused execution. */\n async resumeExecution(executionId: string): Promise<{ data: { resumed: boolean } }> {\n return request(baseUrl, `/api/v1/workflows/executions/${executionId}/resume`, apiKey, { method: \"POST\" });\n },\n\n /** Stop an execution. */\n async stopExecution(executionId: string): Promise<{ data: { stopped: boolean } }> {\n return request(baseUrl, `/api/v1/workflows/executions/${executionId}/stop`, apiKey, { method: \"POST\" });\n },\n\n /** Get the trigger status (e.g. schedule / webhook wiring) for a workflow. */\n async getTriggerStatus(workflowId: string): Promise<{ data: { status: string; details: Record<string, unknown> } }> {\n return request(baseUrl, `/api/v1/workflows/${workflowId}/trigger-status`, apiKey);\n },\n\n /** Reset a workflow's trigger cursor / state. */\n async resetTrigger(workflowId: string): Promise<{ data: { reset: boolean } }> {\n return request(baseUrl, `/api/v1/workflows/${workflowId}/trigger-reset`, apiKey, { method: \"POST\" });\n },\n\n /** Catalog of available workflow node types with config + output schemas. */\n async nodeTypes(params: { type?: string } = {}): Promise<{ data: NodeTypeSchema[] }> {\n return request(baseUrl, \"/api/v1/workflows/node-types/schema\", apiKey, {\n query: params as Record<string, unknown>,\n });\n },\n\n /** Slack users available to workflow nodes. */\n async listSlackUsers(): Promise<{ data: Array<{ id: string; name: string; email: string | null }> }> {\n return request(baseUrl, \"/api/v1/workflows/integrations/slack/users\", apiKey);\n },\n\n /** Slack channels available to workflow nodes. */\n async listSlackChannels(): Promise<{ data: Array<{ id: string; name: string; is_private: boolean }> }> {\n return request(baseUrl, \"/api/v1/workflows/integrations/slack/channels\", apiKey);\n },\n\n /** Roam users available to workflow nodes. */\n async listRoamUsers(): Promise<{ data: Array<{ id: string; name: string; email: string | null }> }> {\n return request(baseUrl, \"/api/v1/workflows/integrations/roam/users\", apiKey);\n },\n\n /** Roam groups available to workflow nodes. */\n async listRoamGroups(): Promise<{ data: Array<{ id: string; name: string }> }> {\n return request(baseUrl, \"/api/v1/workflows/integrations/roam/groups\", apiKey);\n },\n\n /** MCP servers available to workflow nodes. */\n async listMcpServers(): Promise<{ data: Array<{ id: string; name: string; url: string }> }> {\n return request(baseUrl, \"/api/v1/workflows/mcp-servers\", apiKey);\n },\n\n /** Disposition options available to workflow nodes. */\n async listDispositions(): Promise<{ data: Array<{ id: string; label: string }> }> {\n return request(baseUrl, \"/api/v1/workflows/dispositions\", apiKey);\n },\n\n /** Form field definitions for a given form (used by form-trigger nodes). */\n async listFormFields(formId: string): Promise<{ data: Array<{ name: string; type: string; required: boolean }> }> {\n return request(baseUrl, `/api/v1/workflows/forms/${formId}/fields`, apiKey);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport type SkillType = \"llm\" | \"api\";\n\nexport interface SkillInputField {\n name: string;\n type: string;\n required: boolean;\n description?: string;\n}\n\nexport interface Skill {\n id: string;\n title: string;\n description: string | null;\n type: SkillType;\n /** Only present on `type=llm`. */\n prompt?: string;\n /** Only present on `type=llm`. */\n model?: string;\n /** Only present on `type=api`. */\n method?: \"GET\" | \"POST\" | \"PATCH\" | \"PUT\" | \"DELETE\";\n /** Only present on `type=api`. */\n url?: string;\n /** Only present on `type=api`. */\n headers?: Record<string, string>;\n /** Only present on `type=api`. */\n body_template?: string;\n input_schema: { fields: SkillInputField[] };\n output_schema: Record<string, unknown> | null;\n created_at: string | null;\n updated_at: string | null;\n}\n\nexport interface SkillCreateLLMParams {\n title: string;\n description?: string;\n prompt: string;\n model: string;\n input_schema: { fields: SkillInputField[] };\n output_schema?: Record<string, unknown>;\n}\n\nexport interface SkillCreateAPIParams {\n title: string;\n description?: string;\n method: \"GET\" | \"POST\" | \"PATCH\" | \"PUT\" | \"DELETE\";\n url: string;\n headers?: Record<string, string>;\n body_template?: string;\n response_mapping?: Record<string, string>;\n input_schema: { fields: SkillInputField[] };\n}\n\nexport interface SkillUpdateLLMParams {\n title?: string;\n description?: string;\n prompt?: string;\n model?: string;\n input_schema?: { fields: SkillInputField[] };\n output_schema?: Record<string, unknown>;\n}\n\nexport interface SkillUpdateAPIParams {\n title?: string;\n description?: string;\n method?: \"GET\" | \"POST\" | \"PATCH\" | \"PUT\" | \"DELETE\";\n url?: string;\n headers?: Record<string, string>;\n body_template?: string;\n response_mapping?: Record<string, string>;\n input_schema?: { fields: SkillInputField[] };\n}\n\nexport interface SkillTemplate {\n id: string;\n title: string;\n description: string;\n type: SkillType;\n use_cases: string[];\n}\n\nexport interface SkillListParams {\n page?: number;\n limit?: number;\n type?: SkillType;\n search?: string;\n}\n\n/**\n * Skills API - LLM and API building blocks that workflows compose into runs.\n * Requires API key (server-side).\n *\n * Backed by:\n * GET /api/v1/skills\n * GET /api/v1/skills/{id}\n * GET /api/v1/skills/{id}/variables\n * GET /api/v1/skills/models\n * GET /api/v1/skills/templates\n * POST /api/v1/skills (both llm + api types via `type` field)\n * POST /api/v1/skills/from-template\n * POST /api/v1/skills/from-node\n * PUT /api/v1/skills/{id}\n * DELETE /api/v1/skills/{id}\n * POST /api/v1/skills/validate\n * POST /api/v1/skills/{id}/execute\n */\nexport const createSkillsClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n return {\n /** List skills. */\n async list(params: SkillListParams = {}): Promise<{ data: Skill[] }> {\n return request(baseUrl, \"/api/v1/skills\", apiKey, { query: params as Record<string, unknown> });\n },\n\n /** Get a skill by ID. */\n async get(skillId: string): Promise<Skill> {\n const resp = await request<{ data?: Skill }>(baseUrl, `/api/v1/skills/${skillId}`, apiKey);\n return resp.data ?? (resp as unknown as Skill);\n },\n\n /** Get the variables required by a skill (extracted from prompt or body template). */\n async getVariables(skillId: string): Promise<{ data: SkillInputField[] }> {\n return request(baseUrl, `/api/v1/skills/${skillId}/variables`, apiKey);\n },\n\n /** List available LLM models. */\n async listModels(): Promise<{ data: Array<{ id: string; label: string; provider: string }> }> {\n return request(baseUrl, \"/api/v1/skills/models\", apiKey);\n },\n\n /** List skill templates. */\n async listTemplates(params: { type?: SkillType } = {}): Promise<{ data: SkillTemplate[] }> {\n return request(baseUrl, \"/api/v1/skills/templates\", apiKey, { query: params as Record<string, unknown> });\n },\n\n /** Create an LLM skill (prompt + model + schemas). */\n async createLLM(params: SkillCreateLLMParams): Promise<Skill> {\n const resp = await request<{ data?: Skill }>(baseUrl, \"/api/v1/skills\", apiKey, {\n method: \"POST\",\n body: { ...params, type: \"llm\" },\n });\n return resp.data ?? (resp as unknown as Skill);\n },\n\n /** Create an API skill (HTTP request wrapper). */\n async createAPI(params: SkillCreateAPIParams): Promise<Skill> {\n const resp = await request<{ data?: Skill }>(baseUrl, \"/api/v1/skills\", apiKey, {\n method: \"POST\",\n body: { ...params, type: \"api\" },\n });\n return resp.data ?? (resp as unknown as Skill);\n },\n\n /** Create a skill from a built-in template. */\n async createFromTemplate(params: { title: string; template_id: string; overrides?: Record<string, unknown> }): Promise<Skill> {\n const resp = await request<{ data?: Skill }>(baseUrl, \"/api/v1/skills/from-template\", apiKey, {\n method: \"POST\",\n body: params,\n });\n return resp.data ?? (resp as unknown as Skill);\n },\n\n /** Lift a workflow node into a reusable skill. */\n async createFromNode(params: {\n title: string;\n description?: string;\n node_id: string;\n input_mapping?: Record<string, string>;\n output_mapping?: Record<string, string>;\n }): Promise<Skill> {\n const resp = await request<{ data?: Skill }>(baseUrl, \"/api/v1/skills/from-node\", apiKey, {\n method: \"POST\",\n body: params,\n });\n return resp.data ?? (resp as unknown as Skill);\n },\n\n /** Update an LLM skill. */\n async updateLLM(skillId: string, fields: SkillUpdateLLMParams): Promise<Skill> {\n const resp = await request<{ data?: Skill }>(baseUrl, `/api/v1/skills/${skillId}`, apiKey, {\n method: \"PUT\",\n body: { ...fields, type: \"llm\" },\n });\n return resp.data ?? (resp as unknown as Skill);\n },\n\n /** Update an API skill. */\n async updateAPI(skillId: string, fields: SkillUpdateAPIParams): Promise<Skill> {\n const resp = await request<{ data?: Skill }>(baseUrl, `/api/v1/skills/${skillId}`, apiKey, {\n method: \"PUT\",\n body: { ...fields, type: \"api\" },\n });\n return resp.data ?? (resp as unknown as Skill);\n },\n\n /** Delete a skill (irreversible if in-use workflows exist). */\n async delete(skillId: string): Promise<{ data: { deleted: boolean } }> {\n return request(baseUrl, `/api/v1/skills/${skillId}`, apiKey, { method: \"DELETE\" });\n },\n\n /** Validate a skill definition (without saving). */\n async validate(skill: Partial<Skill>): Promise<{ data: { valid: boolean; errors: string[] } }> {\n return request(baseUrl, \"/api/v1/skills/validate\", apiKey, { method: \"POST\", body: skill });\n },\n\n /** Execute a skill immediately with an input payload (test / preview). */\n async execute(skillId: string, inputPayload: Record<string, unknown>): Promise<{\n data: { output: Record<string, unknown>; latency_ms: number; tokens?: number; error: string | null };\n }> {\n return request(baseUrl, `/api/v1/skills/${skillId}/execute`, apiKey, { method: \"POST\", body: inputPayload });\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface IntentKeyword {\n id: string;\n keyword: string;\n domain: string | null;\n include_patterns: string[];\n exclude_patterns: string[];\n page_count: number;\n visitor_count: number;\n company_count: number;\n contact_count: number;\n created_at: string | null;\n}\n\nexport interface IntentPage {\n url: string;\n title: string | null;\n keyword: string | null;\n domain: string;\n visitor_count: number;\n last_seen: string | null;\n}\n\nexport interface IntentVisitor {\n visitor_id: string;\n company_domain: string | null;\n company_name: string | null;\n page_url: string;\n first_seen: string | null;\n last_seen: string | null;\n visit_count: number;\n}\n\nexport interface IntentCompany {\n domain: string;\n name: string | null;\n industry: string | null;\n employee_count: string | null;\n visit_count: number;\n last_seen: string | null;\n}\n\nexport interface IntentContact {\n contact_id: number | null;\n email: string | null;\n full_name: string | null;\n company: string | null;\n job_title: string | null;\n last_seen: string | null;\n}\n\nexport interface IntentStats {\n total_keywords: number;\n total_pages: number;\n total_visitors_30d: number;\n total_companies_30d: number;\n}\n\n/**\n * Intent + visitor tracking. Distinct from `g8.signals` (which is summary scoring) —\n * this module exposes keyword tracking, page-level visitor data, and account-level\n * intent signals from your own site (or from competitor URLs you've added).\n *\n * Requires API key (server-side).\n *\n * Backed by:\n * GET /api/v1/intent/stats\n * POST /api/v1/intent/keywords/list\n * POST /api/v1/intent/keywords/create-from-domain\n * DELETE /api/v1/intent/keywords/{keyword_id}\n * POST /api/v1/intent/keywords/{keyword_id}/companies\n * POST /api/v1/intent/keywords/{keyword_id}/contacts\n * POST /api/v1/intent/keywords/{keyword_id}/urls\n * POST /api/v1/intent/pages-by-domain\n * POST /api/v1/intent/pages/search\n * POST /api/v1/intent/pages/visitors\n * POST /api/v1/intent/pages/contacts\n * POST /api/v1/intent/pages/visitor-counts\n * POST /intent-search/url-companies (note: bare host, no /api/v1 prefix)\n */\nexport const createIntentClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n const get = (path: string) => request<any>(baseUrl, `/api/v1${path}`, apiKey);\n const post = (path: string, body: Record<string, unknown> = {}) =>\n request<any>(baseUrl, `/api/v1${path}`, apiKey, { method: \"POST\", body });\n const del = (path: string) => request<any>(baseUrl, `/api/v1${path}`, apiKey, { method: \"DELETE\" });\n\n return {\n /** Org-level intent stats (totals over the last 30 days). */\n async stats(): Promise<{ data: IntentStats }> {\n return get(\"/intent/stats\");\n },\n\n /** List tracked keywords with optional pagination. */\n async listKeywords(params: { page?: number; limit?: number; search?: string } = {}): Promise<{ data: IntentKeyword[] }> {\n return post(\"/intent/keywords/list\", params);\n },\n\n /** Create a keyword group from a domain (auto-tracks all pages). */\n async createFromDomain(domain: string): Promise<{ data: IntentKeyword }> {\n return post(\"/intent/keywords/create-from-domain\", { domain });\n },\n\n /** Stop tracking a keyword (irreversible — historical data is retained). */\n async deleteKeyword(keywordId: string): Promise<{ data: { deleted: boolean } }> {\n return del(`/intent/keywords/${keywordId}`);\n },\n\n /** Companies showing interest in a tracked keyword. */\n async keywordCompanies(keywordId: string, params: { limit?: number; date_from?: string; date_to?: string } = {}): Promise<{ data: IntentCompany[] }> {\n return post(`/intent/keywords/${keywordId}/companies`, params);\n },\n\n /** Contacts showing interest in a tracked keyword. */\n async keywordContacts(keywordId: string, params: { limit?: number; date_from?: string; date_to?: string } = {}): Promise<{ data: IntentContact[] }> {\n return post(`/intent/keywords/${keywordId}/contacts`, params);\n },\n\n /** URLs associated with a keyword (pages visitors landed on while interested). */\n async keywordUrls(keywordId: string, params: { limit?: number } = {}): Promise<{ data: IntentPage[] }> {\n return post(`/intent/keywords/${keywordId}/urls`, params);\n },\n\n /** Pages tracked on a specific domain. */\n async pagesByDomain(domain: string, params: { limit?: number } = {}): Promise<{ data: IntentPage[] }> {\n return post(\"/intent/pages-by-domain\", { domain, ...params });\n },\n\n /** Search tracked pages by URL fragment or keyword. */\n async searchPages(query: string, params: { limit?: number } = {}): Promise<{ data: IntentPage[] }> {\n return post(\"/intent/pages/search\", { query, ...params });\n },\n\n /** Get visitor records for a specific page URL. */\n async pageVisitors(pageUrl: string, params: { limit?: number; date_from?: string; date_to?: string } = {}): Promise<{ data: IntentVisitor[] }> {\n return post(\"/intent/pages/visitors\", { url: pageUrl, ...params });\n },\n\n /** Get contacts who visited a specific page URL. */\n async pageContacts(pageUrl: string, params: { limit?: number } = {}): Promise<{ data: IntentContact[] }> {\n return post(\"/intent/pages/contacts\", { url: pageUrl, ...params });\n },\n\n /** Visitor count aggregates by page (pass an array of URLs). */\n async pageVisitorCounts(urls: string[]): Promise<{ data: Array<{ url: string; visitor_count: number }> }> {\n return post(\"/intent/pages/visitor-counts\", { urls });\n },\n\n /**\n * Find companies whose users visited a specific URL (intent search).\n *\n * Note: this endpoint lives at the bare host (no `/api/v1` prefix), unlike the rest\n * of the intent surface — we call it directly here instead of through the shared `post()` helper.\n */\n async urlCompanies(url: string, params: { limit?: number; date_from?: string; date_to?: string } = {}): Promise<{ data: IntentCompany[] }> {\n return request<{ data: IntentCompany[] }>(baseUrl, \"/intent-search/url-companies\", apiKey, {\n method: \"POST\",\n body: { url, ...params },\n });\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface GlobalContextDocument {\n id: string;\n category: string;\n title: string;\n content: string;\n metadata: Record<string, unknown> | null;\n created_at: string | null;\n updated_at: string | null;\n}\n\nexport interface Persona {\n id: string;\n name: string;\n description: string | null;\n status: string;\n pain_points: string[];\n goals: string[];\n channels: string[];\n created_at: string | null;\n}\n\nexport interface ICP {\n id: string;\n name: string;\n description: string | null;\n status: string;\n industry: string[] | null;\n employee_count_min: number | null;\n employee_count_max: number | null;\n revenue_min: number | null;\n revenue_max: number | null;\n countries: string[] | null;\n created_at: string | null;\n}\n\nexport interface IntelligenceData {\n id: string;\n source_type: string;\n url: string | null;\n title: string | null;\n content_summary: string | null;\n collected_at: string | null;\n}\n\nexport interface ResearchReport {\n id: string;\n category: \"buyer_psychology\" | \"competitive_teardown\" | \"gtm_channel\" | \"industry_analyst\" | \"review_sentiment\" | \"voice_of_customer\";\n title: string;\n summary: string | null;\n created_at: string | null;\n}\n\n/**\n * Studio context — org-level intelligence documents. The 44-doc engine that\n * powers campaign ideation: brand brief, value props, messaging house, ICPs,\n * personas, intelligence (scrapes + enrichment), and AI research reports.\n *\n * Requires API key (server-side).\n *\n * Backed by:\n * GET /api/v1/global-context/documents\n * GET /api/v1/icps POST /api/v1/icps PATCH /api/v1/icps/{id} POST /api/v1/icps/{id}/archive\n * GET /api/v1/personas POST /api/v1/personas PATCH /api/v1/personas/{id} POST /api/v1/personas/{id}/archive\n * GET /api/v1/intelligence-data\n * GET /api/v1/research-reports\n */\nexport const createStudioClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n const get = (path: string, params: object = {}) =>\n request<any>(baseUrl, `/api/v1${path}`, apiKey, { query: params as Record<string, unknown> });\n const post = (path: string, body: object = {}) =>\n request<any>(baseUrl, `/api/v1${path}`, apiKey, { method: \"POST\", body });\n const patch = (path: string, body: object = {}) =>\n request<any>(baseUrl, `/api/v1${path}`, apiKey, { method: \"PATCH\", body });\n\n return {\n /** Org-level Studio documents (brand_brief, value_props, messaging_house, etc.).\n * `include_content` defaults to true server-side, so each document includes\n * its `content` body unless you explicitly pass `include_content: false`. */\n async globalContext(\n params: { category?: string; limit?: number; include_content?: boolean } = {}\n ): Promise<{ data: GlobalContextDocument[] }> {\n return get(\"/global-context/documents\", params);\n },\n\n /** ICP definitions. */\n async icps(params: { status?: string; limit?: number } = {}): Promise<{ data: ICP[] }> {\n return get(\"/icps\", params);\n },\n\n /** Buyer persona definitions. */\n async personas(params: { status?: string; limit?: number } = {}): Promise<{ data: Persona[] }> {\n return get(\"/personas\", params);\n },\n\n /** Intelligence data (website scrapes, enrichment, competitor research). */\n async intelligenceData(params: { source_type?: string; limit?: number } = {}): Promise<{ data: IntelligenceData[] }> {\n return get(\"/intelligence-data\", params);\n },\n\n /** AI research reports (buyer psychology, competitive teardown, GTM channel, etc.). */\n async researchReports(params: { category?: string; limit?: number } = {}): Promise<{ data: ResearchReport[] }> {\n return get(\"/research-reports\", params);\n },\n\n /** Create an ICP manually (no AI scoring). Requires name + website_url. */\n async createIcp(body: {\n name: string;\n website_url: string;\n description?: string;\n firmographics?: Record<string, unknown>;\n tech_stack?: Record<string, unknown>;\n buying_signals?: unknown[];\n estimated_market_size?: number;\n }): Promise<{ data: ICP }> {\n return post(\"/icps\", body);\n },\n\n /** Update an ICP (partial - send only fields to change). */\n async updateIcp(\n icpId: string,\n body: {\n name?: string;\n description?: string;\n firmographics?: Record<string, unknown>;\n tech_stack?: Record<string, unknown>;\n buying_signals?: unknown[];\n estimated_market_size?: number;\n }\n ): Promise<{ data: ICP }> {\n return patch(`/icps/${icpId}`, body);\n },\n\n /** Archive an ICP (soft delete - sets status to \"archived\"). */\n async archiveIcp(icpId: string): Promise<{ data: ICP }> {\n return post(`/icps/${icpId}/archive`);\n },\n\n /** Create a buyer persona manually (no AI generation). Requires title + website_url. */\n async createPersona(body: {\n title: string;\n website_url: string;\n priority?: number;\n confidence?: string;\n why_target?: string;\n key_signals?: unknown[];\n expected_receptivity?: string;\n campaign_approach?: string;\n recommended_goal?: string;\n source?: string;\n }): Promise<{ data: Persona }> {\n return post(\"/personas\", body);\n },\n\n /** Update a persona (partial). Passing status \"archived\" is equivalent to archivePersona. */\n async updatePersona(\n personaId: string,\n body: {\n title?: string;\n priority?: number;\n confidence?: string;\n why_target?: string;\n key_signals?: unknown[];\n expected_receptivity?: string;\n campaign_approach?: string;\n recommended_goal?: string;\n status?: string;\n }\n ): Promise<{ data: Persona }> {\n return patch(`/personas/${personaId}`, body);\n },\n\n /** Archive a persona (soft delete - sets status to \"archived\"). */\n async archivePersona(personaId: string): Promise<{ data: Persona }> {\n return post(`/personas/${personaId}/archive`);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface MeetingAttendee {\n name: string | null;\n email: string;\n role: \"host\" | \"prospect\" | \"guest\" | string;\n contact_id?: number | null;\n}\n\nexport interface MeetingTranscriptLine {\n speaker: string;\n text: string;\n timestamp: number;\n}\n\nexport interface MeetingAnalysis {\n sentiment: \"positive\" | \"neutral\" | \"negative\";\n summary: string;\n next_steps: string[];\n objections: string[];\n talk_listen_ratio: number | null;\n}\n\nexport interface MeetingSummary {\n id: string;\n status: \"scheduled\" | \"completed\" | \"cancelled\" | \"no_show\";\n event_type: string | null;\n scheduled_at: string;\n duration_minutes: number;\n attendees: MeetingAttendee[];\n contact_id: number | null;\n conferencing_provider: string | null;\n conferencing_url: string | null;\n recording_url: string | null;\n created_at: string;\n}\n\nexport interface MeetingDetail extends MeetingSummary {\n transcript: MeetingTranscriptLine[] | null;\n analysis: MeetingAnalysis | null;\n}\n\nexport interface MeetingListParams {\n status?: \"scheduled\" | \"completed\" | \"cancelled\" | \"no_show\";\n date_from?: string;\n date_to?: string;\n attendee_id?: string;\n event_type?: string;\n contact_id?: number;\n page?: number;\n limit?: number;\n}\n\n/**\n * Meetings API - read-only access to scheduled, completed, and cancelled meetings.\n * Booking happens via `g8.calendar.*` (write-key safe, browser only) — this surface\n * is for reading meeting records, transcripts, and AI analysis.\n *\n * Requires API key (server-side).\n *\n * Backed by:\n * GET /api/v1/inbox/meetings\n * GET /api/v1/inbox/meetings/{meeting_id}\n */\nexport const createMeetingsClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** List meetings with optional filters. Returns summary rows without transcript / analysis. */\n async list(params: MeetingListParams = {}): Promise<{ data: MeetingSummary[]; pagination?: { page: number; limit: number; total: number; has_next: boolean } }> {\n return request(baseUrl, \"/api/v1/inbox/meetings\", apiKey, { query: params as Record<string, unknown> });\n },\n\n /** Get full meeting detail including transcript + AI analysis (transcript available 1-5 min after meeting ends). */\n async get(meetingId: string): Promise<MeetingDetail> {\n const resp = await request<{ data?: MeetingDetail }>(baseUrl, `/api/v1/inbox/meetings/${meetingId}`, apiKey);\n return resp.data ?? (resp as unknown as MeetingDetail);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\n/** Ad platform an audience can sync to. */\nexport type AudienceSyncPlatform = \"meta\" | \"linkedin\" | \"google\" | \"x\";\n/** Sync mode: full mirror, or only ever add members. */\nexport type AudienceSyncMode = \"mirror\" | \"append_only\";\n\nexport interface AudienceSync {\n id: number;\n audience_id: number;\n platform: string;\n platform_audience_name: string | null;\n mode: string;\n refresh_cadence_hours: number;\n is_active: boolean;\n status: string | null;\n last_sync_at: string | null;\n created_at: string | null;\n}\n\nexport interface AudienceSyncCreateParams {\n /** Audience list ID to sync. */\n audience_id: number;\n platform: AudienceSyncPlatform;\n platform_audience_name?: string;\n /** Default \"mirror\". */\n mode?: AudienceSyncMode;\n /** Refresh cadence in hours (0-720; default 24). */\n refresh_cadence_hours?: number;\n /** Platform-specific config (OAuth creds, ad-account ids, etc.). */\n platform_config?: Record<string, unknown>;\n /** Audience list IDs whose members should be suppressed from the sync. */\n suppression_list_ids?: number[];\n}\n\nexport interface AudienceSyncUpdateParams {\n mode?: AudienceSyncMode;\n refresh_cadence_hours?: number;\n is_active?: boolean;\n suppression_list_ids?: number[];\n}\n\nexport interface AudienceSyncRun {\n id: number;\n started_at: string | null;\n finished_at: string | null;\n status: string | null;\n members_added: number | null;\n members_removed: number | null;\n total_members: number | null;\n error_message: string | null;\n}\n\nexport interface AudienceSyncError {\n id: number;\n started_at: string | null;\n error_message: string | null;\n details: Record<string, unknown> | null;\n}\n\n/**\n * Audiences API — sync an audience list to ad platforms (Meta, LinkedIn,\n * Google, X). Requires API key (server-side). Built on the hardened HTTP core,\n * so every method throws a typed `G8Error` on failure and retries transient\n * 429/5xx/network errors.\n *\n * Backed by `/api/v1/audience-syncs`.\n */\nexport const createAudiencesClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n const base = \"/api/v1/audience-syncs\";\n\n return {\n /** List all audience syncs for the organization. */\n async list(): Promise<{ data: AudienceSync[] }> {\n return request(baseUrl, base, apiKey);\n },\n\n /** Create a new audience sync to an ad platform. */\n async create(params: AudienceSyncCreateParams): Promise<AudienceSync> {\n const resp = await request<{ data?: AudienceSync }>(baseUrl, base, apiKey, {\n method: \"POST\",\n body: params,\n });\n return resp.data ?? (resp as unknown as AudienceSync);\n },\n\n /** Get a single audience sync by ID. */\n async get(configId: number): Promise<AudienceSync> {\n const resp = await request<{ data?: AudienceSync }>(baseUrl, `${base}/${configId}`, apiKey);\n return resp.data ?? (resp as unknown as AudienceSync);\n },\n\n /** Update an audience sync (partial). */\n async update(configId: number, fields: AudienceSyncUpdateParams): Promise<AudienceSync> {\n const resp = await request<{ data?: AudienceSync }>(baseUrl, `${base}/${configId}`, apiKey, {\n method: \"PATCH\",\n body: fields,\n });\n return resp.data ?? (resp as unknown as AudienceSync);\n },\n\n /** Delete an audience sync. */\n async delete(configId: number): Promise<{ data: Record<string, unknown> }> {\n return request(baseUrl, `${base}/${configId}`, apiKey, { method: \"DELETE\" });\n },\n\n /** Trigger an immediate sync run for a config. */\n async trigger(configId: number): Promise<{ data: Record<string, unknown> }> {\n return request(baseUrl, `${base}/${configId}/trigger`, apiKey, { method: \"POST\" });\n },\n\n /** List recent sync runs for a config (most recent first). */\n async runs(configId: number): Promise<{ data: AudienceSyncRun[] }> {\n return request(baseUrl, `${base}/${configId}/runs`, apiKey);\n },\n\n /** List recent sync errors for a config. */\n async errors(configId: number): Promise<{ data: AudienceSyncError[] }> {\n return request(baseUrl, `${base}/${configId}/errors`, apiKey);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\n/** Filter operators supported by open-data search. */\nexport type SearchOperator =\n | \"any_of\"\n | \"contains\"\n | \"all_of\"\n | \"none_of\"\n | \"is_empty\"\n | \"is_not_empty\"\n | \"between\"\n | \"exists\";\n\n/** A single search filter condition (named to avoid colliding with enrich's `SearchFilter`). */\nexport interface SearchCondition {\n /** Field to filter on, e.g. \"job_title\", \"country\", \"industry\". */\n field: string;\n operator: SearchOperator;\n /** Filter values (operator-dependent; e.g. `[\"VP\", \"Director\"]` for any_of). */\n value?: unknown[];\n}\n\nexport interface SearchParams {\n /** Filter conditions, combined with AND. */\n filters?: SearchCondition[];\n /** Page number, 1-indexed (1-100). */\n page?: number;\n /** Results per page (1-100, default 25). */\n limit?: number;\n}\n\nexport interface SearchSaveParams extends SearchParams {\n /** Title for the new list the matched records are saved into. */\n list_title: string;\n /** Max records to save (1-10,000, default 1,000). */\n max_results?: number;\n}\n\nexport interface SearchContactItem {\n first_name?: string | null;\n last_name?: string | null;\n middle_name?: string | null;\n work_email?: string | null;\n personal_emails?: string | null;\n direct_phone?: string | null;\n mobile_phone?: string | null;\n job_title?: string | null;\n job_department?: string | null;\n seniority_level?: string | null;\n role?: string | null;\n linkedin_url?: string | null;\n linkedin_headline?: string | null;\n city?: string | null;\n state?: string | null;\n country?: string | null;\n company_name?: string | null;\n company_domain?: string | null;\n company_industry?: string | null;\n company_employee_count?: string | null;\n company_country?: string | null;\n confidence_score?: number | null;\n}\n\nexport interface SearchCompanyItem {\n name?: string | null;\n domain?: string | null;\n website?: string | null;\n description?: string | null;\n industry?: string | null;\n industry_group?: string | null;\n employee_count?: string | null;\n revenue?: string | null;\n founded_year?: number | null;\n phone?: string | null;\n address?: string | null;\n city?: string | null;\n state?: string | null;\n country?: string | null;\n zip?: number | null;\n linkedin_url?: string | null;\n linkedin_followers?: string | null;\n facebook_url?: string | null;\n twitter_url?: string | null;\n crunchbase_url?: string | null;\n logo_url?: string | null;\n}\n\nexport interface SearchSaveResult {\n list_id: number;\n list_title: string;\n estimated_total: number;\n status: string;\n}\n\n/**\n * Search API — prospect the open-data graph for new contacts and companies by\n * filter, and optionally save the matches straight into a list. Requires API\n * key (server-side). Built on the hardened HTTP core, so every method throws a\n * typed `G8Error` on failure and retries transient errors.\n *\n * Backed by `/api/v1/search`.\n */\nexport const createSearchClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n const body = (p: SearchParams) => ({ filters: [], page: 1, limit: 25, ...p });\n\n return {\n /** Search open-data contacts by filter. */\n async contacts(params: SearchParams = {}): Promise<{ data: SearchContactItem[] }> {\n return request(baseUrl, \"/api/v1/search/contacts\", apiKey, { method: \"POST\", body: body(params) });\n },\n\n /** Search open-data companies by filter. */\n async companies(params: SearchParams = {}): Promise<{ data: SearchCompanyItem[] }> {\n return request(baseUrl, \"/api/v1/search/companies\", apiKey, { method: \"POST\", body: body(params) });\n },\n\n /** Search contacts and save the matches into a new list. */\n async saveContacts(params: SearchSaveParams): Promise<SearchSaveResult> {\n const resp = await request<{ data?: SearchSaveResult }>(baseUrl, \"/api/v1/search/contacts/save\", apiKey, {\n method: \"POST\",\n body: { filters: [], page: 1, limit: 25, max_results: 1000, ...params },\n });\n return resp.data ?? (resp as unknown as SearchSaveResult);\n },\n\n /** Search companies and save the matches into a new list. */\n async saveCompanies(params: SearchSaveParams): Promise<SearchSaveResult> {\n const resp = await request<{ data?: SearchSaveResult }>(baseUrl, \"/api/v1/search/companies/save\", apiKey, {\n method: \"POST\",\n body: { filters: [], page: 1, limit: 25, max_results: 1000, ...params },\n });\n return resp.data ?? (resp as unknown as SearchSaveResult);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface AgencyInfo {\n agency_org_id: string;\n agency_org_name: string | null;\n is_agency: boolean;\n client_count: number;\n /** Request header to set when operating a client org (e.g. \"X-Target-Org-Id\"). */\n target_header: string;\n}\n\nexport interface AgencyClient {\n /** Pass this as the `X-Target-Org-Id` header to operate this client org. */\n org_id: string;\n}\n\n/**\n * Agency API — for agency-scoped API keys (minted with `is_agency: true`).\n * Discover the agency credential and the client orgs it may operate. To act on a\n * client org, set the `X-Target-Org-Id` header (see `target_header`) to that\n * client's `org_id` on your subsequent requests. Requires an agency API key\n * (server-side); a non-agency key gets a `403`.\n *\n * Built on the hardened HTTP core (typed `G8Error` + retries). Backed by\n * `/api/v1/agency`.\n */\nexport const createAgencyClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** Describe the agency credential: agency org + authorized client count. */\n async me(): Promise<AgencyInfo> {\n const resp = await request<{ data?: AgencyInfo }>(baseUrl, \"/api/v1/agency/me\", apiKey);\n return resp.data ?? (resp as unknown as AgencyInfo);\n },\n\n /** List the client orgs this agency key may target via `X-Target-Org-Id`. */\n async clients(): Promise<{ data: AgencyClient[] }> {\n return request(baseUrl, \"/api/v1/agency/clients\", apiKey);\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface MarketplaceProfile {\n id: string;\n email: string;\n first_name?: string | null;\n last_name?: string | null;\n marketplace_role?: string | null;\n country_code?: string | null;\n monthly_rate_usd?: string | null;\n per_meeting_rate_usd?: string | null;\n availability_status?: string | null;\n bio?: string | null;\n is_complete: boolean;\n}\n\nexport interface MarketplaceOffer {\n id: string;\n org_id: string;\n org_name?: string | null;\n sdr_id: string;\n status: string;\n monthly_rate_usd?: string | null;\n per_meeting_rate_usd?: string | null;\n created_at?: string | null;\n}\n\nexport interface MarketplaceHiring {\n id: string;\n org_id: string;\n sdr_id: string;\n status: string;\n sdr_name?: string | null;\n sdr_role?: string | null;\n sdr_email?: string | null;\n monthly_rate_usd?: string | null;\n per_meeting_rate_usd?: string | null;\n started_at?: string | null;\n}\n\n/**\n * Marketplace API — for SDR/AE talent on the graph8 marketplace. View your\n * profile, see pending hire offers and respond to them, and list your active\n * hirings. Requires a personal API key (server-side). Built on the hardened\n * HTTP core, so every method throws a typed `G8Error` on failure and retries\n * transient errors.\n *\n * Backed by `/api/v1/marketplace`.\n */\nexport const createMarketplaceClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n const base = \"/api/v1/marketplace\";\n\n return {\n /** Your own marketplace SDR profile. */\n async profile(): Promise<MarketplaceProfile> {\n const resp = await request<{ data?: MarketplaceProfile }>(baseUrl, `${base}/me/profile`, apiKey);\n return resp.data ?? (resp as unknown as MarketplaceProfile);\n },\n\n /** Pending hire offers you can accept or reject. */\n async offers(): Promise<{ offers: MarketplaceOffer[]; count: number }> {\n const resp = await request<{ data?: { offers: MarketplaceOffer[]; count: number } }>(\n baseUrl,\n `${base}/me/offers`,\n apiKey,\n );\n return resp.data ?? (resp as unknown as { offers: MarketplaceOffer[]; count: number });\n },\n\n /** Accept a pending hire offer (by hiring id). */\n async acceptOffer(hiringId: string): Promise<Record<string, unknown>> {\n const resp = await request<{ data?: Record<string, unknown> }>(\n baseUrl,\n `${base}/me/offers/${hiringId}/accept`,\n apiKey,\n { method: \"POST\" },\n );\n return resp.data ?? (resp as unknown as Record<string, unknown>);\n },\n\n /** Reject a pending hire offer (by hiring id). */\n async rejectOffer(hiringId: string): Promise<Record<string, unknown>> {\n const resp = await request<{ data?: Record<string, unknown> }>(\n baseUrl,\n `${base}/me/offers/${hiringId}/reject`,\n apiKey,\n { method: \"POST\" },\n );\n return resp.data ?? (resp as unknown as Record<string, unknown>);\n },\n\n /** Your active hiring contracts. */\n async hirings(): Promise<{ hirings: MarketplaceHiring[]; count: number }> {\n const resp = await request<{ data?: { hirings: MarketplaceHiring[]; count: number } }>(\n baseUrl,\n `${base}/me/hirings`,\n apiKey,\n );\n return resp.data ?? (resp as unknown as { hirings: MarketplaceHiring[]; count: number });\n },\n };\n};\n","import { request } from \"./http\";\n\nconst DEFAULT_API = \"https://be.graph8.com\";\n\nexport interface Snippet {\n write_key: string;\n tracking_host: string;\n domains: string[];\n /** Ready-to-use React component import for @graph8/nextjs. */\n react_snippet: string;\n /** Vanilla JS script tag for non-React apps. */\n script_tag: string;\n /** Full configuration object (gtm/config.json). */\n config: Record<string, unknown>;\n}\n\n/**\n * Snippet API — fetch your org's graph8 tracking snippet programmatically, to\n * embed the tracker into an app or a customer's site (the write key, a React\n * component, a vanilla `<script>` tag, allowed domains, and the full config).\n * Requires an API key (server-side). Built on the hardened HTTP core, so it\n * throws a typed `G8Error` on failure and retries transient errors.\n *\n * Backed by `GET /api/v1/snippet`.\n */\nexport const createSnippetClient = (apiKey: string, apiUrl?: string) => {\n const baseUrl = apiUrl || DEFAULT_API;\n\n return {\n /** Get your org's tracking snippet (write key + React/script-tag embeds + config). */\n async get(): Promise<Snippet> {\n const resp = await request<{ data?: Snippet }>(baseUrl, \"/api/v1/snippet\", apiKey);\n return resp.data ?? (resp as unknown as Snippet);\n },\n };\n};\n"],"mappings":"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","names":["DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","request","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","DEFAULT_API","module"]}