Installation
- npm
- yarn
- pnpm
npm install newscatcher-catchall-sdk
yarn add newscatcher-catchall-sdk
pnpm add newscatcher-catchall-sdk
Quickstart
Get started with CatchAll in three steps:1
Initialize the client
import { CatchAllApiClient } from "newscatcher-catchall-sdk";
const client = new CatchAllApiClient({ apiKey: "YOUR_API_KEY" });
2
Create a job
const job = await client.jobs.createJob({
query: "AI company acquisitions",
limit: 10,
});
const jobId = job.job_id;
3
Wait and retrieve results
const POLL_INTERVAL_MS = 60000;
// Poll for completion
while (true) {
const status = await client.jobs.getJobStatus({ job_id: jobId });
if (status.status === "completed") {
break;
}
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
}
// Get results
const results = await client.jobs.getJobResults({ job_id: jobId });
console.log(`Found ${results.valid_records} valid records`);
Jobs process asynchronously and typically complete in 10-15 minutes. See the
Quickstart for a complete walkthrough.
Working with jobs
- Get suggestions
- Create and track
- Continue jobs
- Early results
- List jobs
Get suggested validators, enrichments, and date ranges before creating a job:
import { CatchAllApiClient } from "newscatcher-catchall-sdk";
const client = new CatchAllApiClient({ apiKey: "YOUR_API_KEY" });
const suggestions = await client.jobs.initialize({
query: "AI company acquisitions",
context: "Focus on deal size and acquiring company details"
});
console.log(JSON.stringify(suggestions, null, 2));
Show suggestions response
Show suggestions response
{
"validators": [
{
"name": "is_acquisition_event",
"description": "true if article describes a completed or announced acquisition",
"type": "boolean"
},
{
"name": "involves_ai_company",
"description": "true if acquiring or acquired company is in AI sector",
"type": "boolean"
}
],
"enrichments": [
{
"name": "acquirer_company",
"description": "Extract the acquiring company name",
"type": "company"
},
{
"name": "acquired_company",
"description": "Extract the acquired company name",
"type": "company"
},
{
"name": "deal_value",
"description": "Extract acquisition price if mentioned",
"type": "number"
},
{
"name": "announcement_date",
"description": "Extract date of announcement",
"type": "date"
},
{
"name": "acquirer_details",
"description": "Extract details about the acquiring company",
"type": "text"
}
],
"start_date": "2026-02-01T14:12:57.292205+00:00",
"end_date": "2026-02-06T14:12:57.292205+00:00",
"date_modification_message": [
"No dates were provided; using a default window of 5 days (2026-02-01 to 2026-02-06)."
]
}
To learn more, see the Initialize endpoint.
Submit a query and track its progress:
const POLL_INTERVAL_MS = 60000;
// Create job with custom validators and enrichments
const job = await client.jobs.createJob({
query: "AI company acquisitions",
context: "Focus on deal size and acquiring company details",
limit: 10,
validators: [
{
name: "is_acquisition_event",
description: "true if article describes a completed or announced acquisition",
type: "boolean"
}
],
enrichments: [
{
name: "acquirer_company",
description: "Extract the acquiring company name",
type: "company"
},
{
name: "acquired_company",
description: "Extract the acquired company name",
type: "company"
},
{
name: "deal_value",
description: "Extract acquisition price if mentioned",
type: "number"
}
]
});
console.log(`Job created: ${job.job_id}`);
// Monitor progress
const jobId = job.job_id;
while (true) {
const status = await client.jobs.getJobStatus({ job_id: jobId });
if (status.status === "completed") {
break;
}
const currentStep = status.steps.find((s) => !s.completed);
if (currentStep) {
console.log(`Step ${currentStep.order}/7: ${currentStep.status}`);
}
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
}
// Retrieve results
const results = await client.jobs.getJobResults({ job_id: jobId });
console.log(`\nFound ${results.valid_records} valid records`);
for (const record of results.all_records) {
console.log(` ${record.record_title}`);
}
Validators and enrichments are optional. If not provided, the system
generates them automatically based on your query.
Extend processing limits for completed jobs:
const POLL_INTERVAL_MS = 60000;
// Continue job to process more records
const continued = await client.jobs.continueJob({
job_id: jobId,
new_limit: 50,
});
console.log(
`Continued: ${continued.previous_limit} -> ${continued.new_limit} records`
);
// Wait for completion
while (true) {
const status = await client.jobs.getJobStatus({ job_id: jobId });
if (status.status === "completed") {
break;
}
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
}
// Get final results
const finalResults = await client.jobs.getJobResults({ job_id: jobId });
console.log(`Total: ${finalResults.valid_records} valid records`);
Use
limit parameter when creating jobs to start with fewer records for quick testing.
Continue the job if you need more records after reviewing initial results.Retrieve partial results during the enriching stage:
const POLL_INTERVAL_MS = 60000;
while (true) {
const status = await client.jobs.getJobStatus({ job_id: jobId });
if (status.status === "enriching" || status.status === "completed") {
const results = await client.jobs.getJobResults({ job_id: jobId });
if (results.valid_records > 0) {
console.log(
`Progress: ${results.progress_validated}/${results.candidate_records} validated, ${results.valid_records} valid`
);
}
if (status.status === "completed") {
break;
}
}
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
}
Retrieve all jobs created by your account:
const jobs = await client.jobs.getUserJobs();
for (const job of jobs) {
console.log(`Job ${job.job_id}: ${job.query} (${job.status})`);
}
Complete example with all features
Complete example with all features
import { CatchAllApiClient, CatchAllApiError } from "newscatcher-catchall-sdk";
const POLL_INTERVAL_MS = 60000;
const client = new CatchAllApiClient({ apiKey: "YOUR_API_KEY" });
try {
// Create job with custom enrichments
const job = await client.jobs.createJob({
query: "AI company acquisitions",
context: "Focus on deal size and acquiring company details",
limit: 10,
enrichments: [
{
name: "acquirer_company",
description: "Extract the acquiring company name",
type: "company"
},
{
name: "deal_value",
description: "Extract acquisition price if mentioned",
type: "number"
}
]
});
const jobId = job.job_id;
console.log(`Job created: ${jobId}`);
// Poll with early results access
while (true) {
const status = await client.jobs.getJobStatus({ job_id: jobId });
if (status.status === "enriching" || status.status === "completed") {
const results = await client.jobs.getJobResults({ job_id: jobId });
if (results.valid_records > 0) {
console.log(`Progress: ${results.valid_records} valid records`);
}
if (status.status === "completed") {
break;
}
}
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
}
// Continue if needed
let results = await client.jobs.getJobResults({ job_id: jobId });
if (results.valid_records >= 10) {
await client.jobs.continueJob({
job_id: jobId,
new_limit: 50,
});
while (true) {
const status = await client.jobs.getJobStatus({ job_id: jobId });
if (status.status === "completed") {
break;
}
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
}
results = await client.jobs.getJobResults({ job_id: jobId });
}
// Display results
console.log(`\nFinal: ${results.valid_records} valid records`);
for (const record of results.all_records) {
console.log(` ${record.record_title}`);
}
} catch (err) {
if (err instanceof CatchAllApiError) {
console.error(`Status: ${err.statusCode}`);
console.error(`Error: ${err.message}`);
}
}
Working with event monitors
Automate recurring queries with scheduled execution.- Create event monitor
- Update event monitor
- Pause/Resume
- List event monitors
- Retrieve results
Create an event monitor from a completed job:
const monitor = await client.monitors.createMonitor({
reference_job_id: jobId,
schedule: "every day at 12 PM UTC",
webhook_ids: ["a1b2c3d4-e5f6-7890-abcd-ef1234567890"],
});
console.log(`Event monitor created: ${monitor.monitor_id}`);
Event monitors require a minimum 24-hour interval between executions. Learn more in the
Event Monitors documentation.
Update webhook configuration for an existing event monitor:
const updated = await client.monitors.updateMonitor({
monitor_id: monitor.monitor_id,
webhook_ids: ["b2c3d4e5-f6a7-8901-bcde-f12345678901"],
limit: 100,
});
console.log(`Event monitor updated: ${updated.status}`);
Control event monitor execution:
// Pause event monitor
await client.monitors.disableMonitor({ monitor_id: monitor.monitor_id });
console.log("Event monitor paused");
// Resume event monitor
await client.monitors.enableMonitor({ monitor_id: monitor.monitor_id });
console.log("Event monitor resumed");
Retrieve all event monitors for your account:
const monitors = await client.monitors.listMonitors();
console.log(`Total event monitors: ${monitors.total_monitors}`);
for (const m of monitors.monitors) {
const status = m.enabled ? "active" : "paused";
console.log(`${m.monitor_id}: ${status}`);
}
Access aggregated results from all event monitor executions:
// List execution history
const jobs = await client.monitors.listMonitorJobs({
monitor_id: monitor.monitor_id,
sort: "desc",
});
console.log(`Event monitor executed ${jobs.total_jobs} jobs`);
// Get all collected records
const results = await client.monitors.pullMonitorResults({
monitor_id: monitor.monitor_id,
});
console.log(`Total records: ${results.records}`);
for (const record of results.all_records) {
console.log(` ${record.record_title}`);
console.log(` Added: ${record.added_on}`);
}
Complete event monitor example
Complete event monitor example
import { CatchAllApiClient, CatchAllApiError } from "newscatcher-catchall-sdk";
const client = new CatchAllApiClient({ apiKey: "YOUR_API_KEY" });
try {
// Create event monitor from completed job
const jobId = "af7a26d6-cf0b-458c-a6ed-4b6318c74da3";
const monitor = await client.monitors.createMonitor({
reference_job_id: jobId,
schedule: "every day at 12 PM UTC",
webhook_ids: ["a1b2c3d4-e5f6-7890-abcd-ef1234567890"],
});
const monitorId = monitor.monitor_id;
console.log(`Event monitor created: ${monitorId}`);
// Update webhook
await client.monitors.updateMonitor({
monitor_id: monitorId,
webhook_ids: ["b2c3d4e5-f6a7-8901-bcde-f12345678901"],
limit: 100,
});
// List all event monitors
const allMonitors = await client.monitors.listMonitors();
for (const m of allMonitors.monitors) {
const status = m.enabled ? "active" : "paused";
console.log(`${m.monitor_id}: ${status}`);
}
// Control execution
await client.monitors.disableMonitor({ monitor_id: monitorId });
await client.monitors.enableMonitor({ monitor_id: monitorId });
// List execution history
const jobs = await client.monitors.listMonitorJobs({
monitor_id: monitorId,
sort: "desc",
});
console.log(`\nEvent monitor executed ${jobs.total_jobs} jobs`);
for (const job of jobs.jobs) {
console.log(` Job ${job.job_id}: ${job.start_date} to ${job.end_date}`);
}
// Get aggregated results
const results = await client.monitors.pullMonitorResults({
monitor_id: monitorId,
});
console.log(`\nCollected ${results.records} total records`);
for (const record of results.all_records) {
console.log(` ${record.record_title}`);
}
} catch (err) {
if (err instanceof CatchAllApiError) {
console.error(`Status: ${err.statusCode}`);
console.error(`Error: ${err.message}`);
}
}
Company monitors
Company monitors let you track specific companies across jobs. Create entities, group them into a dataset, then connect the dataset to any job to get per-company relevance scores in results.- Create entity
- Create dataset from CSV
- Submit connected job
- Read results
import { CatchAllApiClient } from "newscatcher-catchall-sdk";
const client = new CatchAllApiClient({ apiKey: "YOUR_API_KEY" });
const entity = await client.entities.createEntity({
name: "NewsCatcher",
entity_type: "company",
description: "AI-powered news data provider",
additional_attributes: {
company_attributes: {
domain: "newscatcherapi.com",
alternative_names: ["NC", "NewsCatcher API"],
key_persons: ["Artem Bugara", "Maksym Sugonyaka"],
},
},
});
const entityId = entity.id;
Upload a CSV to create a dataset and entities in one step:CSV format:
import { createReadStream } from "fs";
const dataset = await client.datasets.createDatasetFromCsv({
file: createReadStream("companies.csv"),
name: "My Portfolio",
});
const datasetId = dataset.dataset_id;
name,description,domain,alternative_names,key_persons
NewsCatcher,"AI-powered news data provider",newscatcherapi.com,"NC;NewsCatcher API","Artem Bugara;Maksym Sugonyaka"
OpenAI,"Artificial intelligence research company",openai.com,"Open AI","Sam Altman"
Wait for the dataset to reach
ready status, then submit a job:const POLL_INTERVAL_MS = 5000;
// Poll until ready
while (true) {
const status = await client.datasets.getDataset({ dataset_id: datasetId });
if (status.latest_status === "ready") break;
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
}
// Submit connected job
const job = await client.jobs.createJob({
query: "AI chip partnerships",
connected_dataset_ids: [datasetId],
});
Each record includes a
connected_entities array with relevance scores:const results = await client.jobs.getJobResults({ job_id: job.job_id });
for (const record of results.all_records) {
console.log(record.record_title);
for (const entity of record.connected_entities ?? []) {
console.log(` ${entity.name}: score ${entity.ed_score}/10`);
console.log(` ${entity.relation}`);
}
}
For a full step-by-step walkthrough including batch entity creation and the
JSON API path, see Company Monitors.
Type safety
The SDK exports all request and response types for full TypeScript support:import { CatchAllApi } from "newscatcher-catchall-sdk";
const request: CatchAllApi.SubmitRequestDto = {
query: "AI company acquisitions",
context: "Focus on deal size and acquiring company details",
limit: 10,
};
const job = await client.jobs.createJob(request);
Error handling
Handle API errors with structured exception handling:import { CatchAllApiError } from "newscatcher-catchall-sdk";
try {
await client.jobs.createJob({
query: "AI company acquisitions",
});
} catch (err) {
if (err instanceof CatchAllApiError) {
console.log(`Status: ${err.statusCode}`);
console.log(`Error: ${err.message}`);
}
}
Advanced usage
Pagination
Retrieve large result sets page by page:let page = 1;
while (true) {
const results = await client.jobs.getJobResults({
job_id: jobId,
page: page,
page_size: 100,
});
console.log(`Page ${results.page}/${results.total_pages}`);
for (const record of results.all_records) {
console.log(` ${record.record_title}`);
}
if (results.page >= results.total_pages) {
break;
}
page++;
}
Timeouts
Configure custom timeouts at the request level:const response = await client.jobs.createJob(
{
query: "AI company acquisitions",
},
{
timeoutInSeconds: 30,
}
);
Retries
Configure automatic retry behavior for failed requests:const response = await client.jobs.createJob(
{
query: "AI company acquisitions",
},
{
maxRetries: 3,
}
);
Aborting requests
Cancel requests using an abort signal:const controller = new AbortController();
const response = await client.jobs.createJob(
{
query: "AI company acquisitions",
},
{
abortSignal: controller.signal,
}
);
// Cancel the request
controller.abort();
Runtime compatibility
The SDK works in the following runtimes:- Node.js 18+
- Vercel
- Cloudflare Workers
- Deno v1.25+
- Bun 1.0+
- React Native

