A TypeScript CLI tool for interacting with the Endpoints API programmatically. Use it to list endpoints, inspect metadata, scan documents, manage items, and export data.
- List Endpoints - View all your endpoints organized by category
- Inspect Metadata - See Living JSON data for any endpoint
- Scan Documents - Process files or text with AI extraction
- Create Endpoints - Create new endpoints programmatically
- Append Items - Add items to existing endpoints
- Delete Endpoints - Remove endpoints and all associated files
- Delete Items - Remove individual items from endpoints
- Download Files - Fetch files via presigned S3 URLs
- Export Data - Save endpoint data as JSON for analysis
- Billing Stats - View usage and subscription information
- Node.js 18+
- An Endpoints account with an API key
# Clone the repository
git clone https://github.com/adamkristopher/endpoint-assistant.git
cd endpoint-assistant
# Install dependencies
npm install
# Configure environment
cp .env.example .env- Log in to your Endpoints dashboard
- Navigate to Settings → API Keys
- Click Create New Key
- Give your key a descriptive name (e.g., "CLI Tool")
- Copy the key immediately - it won't be shown again
API keys use the format ep_xxxxxxxxxxxxxxxxxxxx.
Security Note: Keep your API key secret. Never commit it to version control or share it publicly.
Edit your .env file:
# Required: Your Endpoints API base URL
ENDPOINTS_API_URL=https://endpoints.work
# Required: Your API key (starts with ep_)
ENDPOINTS_API_KEY=ep_your_api_key_here| Variable | Required | Description |
|---|---|---|
ENDPOINTS_API_URL |
Yes | Base URL of the Endpoints API |
ENDPOINTS_API_KEY |
Yes | Your API key (ep_xxx format) |
View all your endpoints grouped by category:
npm run overviewOutput:
📁 Endpoints Overview
──────────────────────────────────────────────────
job-tracker/
└─ january-2026
└─ february-2026
receipts/
└─ 2026-q1
──────────────────────────────────────────────────
Total: 2 categories, 3 endpoints
Get detailed metadata for a specific endpoint:
npm run inspect -- /job-tracker/january-2026Process text with AI extraction:
npm run scan -- "track job applications" --text "Applied to Acme Corp as Engineer on Jan 15"Process files with AI extraction:
npm run scan -- "track job applications" --file ./resume.pdfWith a target endpoint:
npm run scan -- "track job applications" --file ./resume.pdf --target /job-tracker/january-2026The prompt parameter controls which endpoint items are added to:
| Prompt Format | Behavior | Example |
|---|---|---|
category name |
Creates new endpoint with AI-generated slug | "job tracker" → /job-tracker/january-2026 |
category - slug |
Adds to existing endpoint | "job-tracker - usds" → /job-tracker/usds |
Examples:
# Create new endpoint (AI determines slug based on content)
npm run scan -- "job tracker" --text "Applied to Acme Corp"
# Add to existing endpoint /job-tracker/usds
npm run scan -- "job-tracker - usds" --text "Follow-up interview scheduled"
# Add to existing endpoint /invoices/acme-corp
npm run scan -- "invoices - acme-corp" --file ./invoice.pdfUse category - slug format when adding multiple documents to the same endpoint.
Create a new empty endpoint:
npm run create -- /projects/q1-2026Create with initial items:
npm run create -- /projects/q1-2026 --items '[{"data":{"name":"Project Alpha"}}]'Add items to an existing endpoint:
npm run append -- /job-tracker/january-2026 '[{"data":{"company":"New Corp","position":"Developer"}}]'Remove an endpoint and all its files:
npm run delete -- /job-tracker/january-2026Remove one item from an endpoint:
npm run delete-item -- abc12345 /job-tracker/january-2026Download a file using its S3 key:
npm run download -- 123/job-tracker/january-2026/resume.pdfFiles are saved to the results/ directory by default.
Export full endpoint data as JSON:
npm start export /job-tracker/january-2026Creates results/job-tracker-january-2026.json.
Check your usage and subscription:
npm run statsOutput:
📊 Billing Stats
──────────────────────────────────────────────────
Tier: hobby
Status: active
Parses: 45 / 200
Storage: 50.0 MB / 500.0 MB
Period ends: 2/15/2026
──────────────────────────────────────────────────
import {
overview,
inspect,
scan,
create,
append,
removeEndpoint,
removeItem,
download,
exportEndpoint,
stats
} from "./src/index.js";
// List all endpoints
await overview();
// Inspect an endpoint
await inspect("/job-tracker/january-2026");
// Scan text
await scan("track jobs", { text: "Applied to Acme Corp" });
// Scan files
await scan("track jobs", { file: "./resume.pdf" });
// Create endpoint
await create("/projects/q1-2026");
// Append items
await append("/job-tracker/january-2026", '[{"data":{}}]');
// Delete endpoint
await removeEndpoint("/job-tracker/january-2026");
// Delete item
await removeItem("abc12345", "/job-tracker/january-2026");
// Download file
await download("123/job-tracker/file.pdf");
// Export endpoint
await exportEndpoint("/job-tracker/january-2026");
// View billing stats
await stats();import {
listEndpoints,
getEndpoint,
deleteEndpoint,
createEndpoint,
appendItems
} from "./src/api/endpoints.js";
// List all endpoints by category
const categories = await listEndpoints();
// Get endpoint details
const details = await getEndpoint("/job-tracker/january-2026");
// Delete endpoint
const result = await deleteEndpoint("/job-tracker/january-2026");
// Create endpoint
const endpoint = await createEndpoint("/projects/q1-2026", {
items: [{ data: { name: "Project" } }]
});
// Append items
const updated = await appendItems("/job-tracker/january-2026", [
{ data: { company: "New Corp" } }
]);import { deleteItem } from "./src/api/items.js";
// Delete a single item
const result = await deleteItem("abc12345", "/job-tracker/january-2026");import { scanText, scanFiles } from "./src/api/scan.js";
// Scan text
const result = await scanText("track jobs", "Applied to Acme Corp");
// Scan files
const file = new File([buffer], "resume.pdf");
const result = await scanFiles("track jobs", [file]);
// With target endpoint
const result = await scanText("track jobs", "text", {
targetEndpoint: "/job-tracker/january-2026"
});import { getFileUrl, downloadFile } from "./src/api/files.js";
// Get a presigned URL (expires in 1 hour by default)
const { url, expiresIn } = await getFileUrl("123/path/to/file.pdf");
// Download file to disk
const savedPath = await downloadFile("123/path/to/file.pdf", "./output/file.pdf");import { getBillingStats } from "./src/api/billing.js";
// Get billing stats
const stats = await getBillingStats();
// Returns: { tier, parsesThisMonth, monthlyParseLimit, storageUsed, ... }This tool interacts with the following Endpoints API routes:
| Endpoint | Method | Description |
|---|---|---|
/api/endpoints/tree |
GET | List endpoints grouped by category |
/api/endpoints/[...path] |
GET | Get endpoint details and metadata |
/api/endpoints/[...path] |
DELETE | Delete endpoint and all files |
/api/endpoints/[...path] |
PATCH | Append items to endpoint |
/api/endpoints |
POST | Create new endpoint |
/api/files/[...key] |
GET | Get presigned URL for file access |
/api/items/[itemId] |
DELETE | Delete single item |
/api/scan |
POST | Scan files/text with AI |
/api/billing/stats |
GET | Get billing stats* |
*Note: /api/billing/stats currently only supports session auth, not API key auth.
All endpoints support Bearer token authentication:
Authorization: Bearer ep_your_api_key_here
endpoint-assistant/
├── src/
│ ├── index.ts # CLI entry point and high-level functions
│ ├── api/
│ │ ├── endpoints.ts # Endpoint CRUD operations
│ │ ├── files.ts # File access (getFileUrl, downloadFile)
│ │ ├── items.ts # Item deletion
│ │ ├── scan.ts # AI scanning (scanText, scanFiles)
│ │ └── billing.ts # Billing stats
│ ├── core/
│ │ └── client.ts # HTTP client with Bearer auth
│ └── config/
│ └── settings.ts # Environment configuration
├── tests/ # Vitest tests (TDD)
├── results/ # Downloaded files and exports
├── .env.example # Environment template
└── package.json
# Run all tests
npm test
# Watch mode
npm run test:watchTests follow the AAA pattern (Arrange, Act, Assert):
it("returns presigned URL for valid file key", async () => {
// Arrange
vi.spyOn(global, "fetch").mockResolvedValue(
new Response(JSON.stringify({ url: "https://...", expiresIn: 3600 }))
);
// Act
const result = await getFileUrl("123/file.pdf");
// Assert
expect(result.url).toContain("https://");
expect(result.expiresIn).toBe(3600);
});- Add mock response to
tests/mocks/responses.ts - Write failing tests first (RED)
- Implement minimum code to pass (GREEN)
- Refactor while keeping tests green
Your .env file is missing or the API key isn't set. Copy .env.example to .env and add your key.
Your API key is invalid or expired. Generate a new one from the Endpoints dashboard.
You're trying to access a file that doesn't belong to your account.
The endpoint path doesn't exist. Use npm run overview to see available endpoints.
You've exceeded your monthly parse limit. Upgrade your plan or wait until the next billing cycle.
MIT
- Fork the repository
- Create a feature branch
- Write tests for new functionality
- Submit a pull request
Built for use with Endpoints - the document tracking platform with Living JSON.