Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/manusapis/Agix/llms.txt

Use this file to discover all available pages before exploring further.

Static spreadsheets go stale the moment you save them. Agix’s data service lets you pull fresh rows from three source types — public web pages, Stripe, and SQL databases — and land them directly into your active worksheet. A built-in comparison utility then diffs incoming data against what is already in the sheet, surfacing new rows, changed values, and statistical anomalies so you always know what changed and why.

The dataService.pull() method

All data ingestion flows through a single entry point in src/services/data/data.service.ts:
async pull(source: DataSourceType, request: DataPullRequest): Promise<DataPullResult>
source
DataSourceType
required
The source to pull from. dataService.pull() currently implements "web", "stripe", and "sql" — passing any other value throws Error: Unsupported data source. The full DataSourceType union (defined in src/types/data.types.ts) is:
type DataSourceType =
  | "web"
  | "stripe"
  | "sql"
  | "salesforce"
  | "hubspot"
  | "google-analytics"
  | "notion"
  | "airtable";
request
DataPullRequest
required
Describes the resource to fetch and any optional filters or row limits.
interface DataPullRequest {
  source: DataSourceType;
  resource: string;           // URL, Stripe object name, or SQL table
  filters?: Record<string, string>;
  limit?: number;
}
The method routes to the correct implementation based on the source value and always returns a DataPullResult:
interface DataPullResult {
  source: DataSourceType;
  resource: string;
  pulledAt: string;             // ISO-8601 timestamp
  rows: Record<string, unknown>[];
  schema: ColumnSchema[];       // name, type, nullable per column
}

Source types

Web

When source is "web", dataService delegates to webScraper.scrape({ url: request.resource }):
import { webScraper } from "./web.scraper";

async pullFromWeb(request: DataPullRequest): Promise<DataPullResult> {
  const scraped = await webScraper.scrape({ url: request.resource });
  return {
    source: "web",
    resource: request.resource,
    pulledAt: new Date().toISOString(),
    rows: scraped.data as Record<string, unknown>[],
    schema: [],
  };
}
The scraper sends an authenticated fetch with a User-Agent: Agix/1.0 header, parses the HTML response, and returns a WebScrapeResult containing structured rows and a scrapedAt timestamp. Additional helpers on the scraper expose table extraction, stock-price lookups, and exchange-rate lookups:
MethodDescription
scrape({ url })Fetch a URL and return structured rows
extractTable(url, tableIndex?)Pull a specific <table> from the page (default: first table)
fetchStockPrice(symbol)Return { symbol, price, currency } for a ticker
fetchExchangeRate(from, to)Return { pair, rate } for a currency pair

Stripe

When source is "stripe", dataService routes to pullFromStripe(). This surfaces your Stripe subscription tiers, payment histories, and customer data as flat rows in the sheet. See the full configuration guide:

Stripe Integration

Connect your Stripe account, choose which objects to pull (charges, subscriptions, customers), and configure automatic refreshes.

SQL

When source is "sql", dataService routes to pullFromSQL(). Point it at any PostgreSQL or MySQL table and pull query results directly into a sheet range. See the full configuration guide:

SQL Integration

Configure a connection string, write a SELECT query, and map result columns to sheet columns with optional type coercion.

Comparing new data against the sheet

After a pull you can diff the incoming rows against an existing range in the active worksheet using compareWithExisting():
const diff = await dataService.compareWithExisting(
  newData,       // Record<string, unknown>[] from a DataPullResult
  "A1:F500"      // The range already in the sheet
);

// diff shape:
// {
//   newRows: number,
//   changedRows: number,
//   anomalies: { row: number; column: string; oldValue: unknown; newValue: unknown }[]
// }
newRows
number
Count of rows present in the new data that have no match in the existing range.
changedRows
number
Count of rows where at least one cell value differs from the existing sheet data.
anomalies
array
Rows and columns where the incoming value is statistically far from what the sheet currently holds. Each entry includes row, column, oldValue, and newValue.

RAG ingestion for large spreadsheets

When a spreadsheet is too large to fit inside a single AI context window, Agix uses the RAG (Retrieval-Augmented Generation) ingestion service at src/services/ingestion/rag.service.ts to break it into searchable chunks.
// Ingest a file — returns a document record with a unique docId
const doc = await ragService.ingest(file);
// doc: { docId, fileName, format, ingestedAt, chunkCount, metadata }

// Query the indexed content
const response = await ragService.query({
  question: "What was the average deal size in Q4?",
  docIds: [doc.docId],
  maxChunks: 8,
});
// response: { answer, sources: [{ docId, fileName, pageNumber, excerpt, relevance }], confidence }
Each ingested document is split into DocumentChunk records. Every chunk stores its content, optional pageNumber, and a vector embedding used for semantic similarity search. When you ask a question, Agix retrieves the most relevant chunks and grounds the AI’s answer in that content — so even a 100,000-row sheet can be queried accurately without hitting token limits. Supported ingest formats: pdf, docx, txt, csv.

Build docs developers (and LLMs) love