Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Meerkat — open source webhook-native agent task API

Meerkat mascot
Describe a task in plain English. Meerkat runs it async — results POST to your webhook.

meerkat-js

Official JavaScript/TypeScript client for Meerkat — an open source, webhook-native API for async agent tasks.

License: MIT

Works in Node.js, Bun, Deno, and browsers with fetch. Includes helpers for Express and Next.js webhook verification.


About Meerkat

Meerkat is open source infrastructure for async agent tasks. You describe work in plain English, connect your own LLM key (BYOK), and Meerkat schedules execution and POSTs signed JSON to your webhook — without building schedulers, scrapers, or retry logic.

Resource Link
Website meerkatagents.com
Documentation meerkatagents.com/docs
Use cases Package tracking · Site monitoring · Agent webhooks
Developer guides meerkatagents.com/blog
Sign up (Cloud) cloud.meerkatagents.com/signup
Open source server github.com/Tiny-Bubble-Company/meerkat

This repo is the official JavaScript/TypeScript package (meerkat-js). For product overview, use cases, and self-host vs Cloud, read more on the Meerkat website.

Other SDKs: meerkat-ruby · meerkat-python


Table of contents


What is Meerkat?

Meerkat gives developers a single primitive for agentic async work:

Register a task → Meerkat runs it → findings POST to your webhook

Describe a task in plain English, pass structured input_params, bring your own LLM key (BYOK), and Meerkat's agent executes the work — fetching webpages, extracting structured findings, and delivering JSON to your output_webhook on a schedule or on demand.

No polling. No per-carrier SDKs. No LLM tool loops to maintain.

This package wraps the Meerkat REST API so you can create tasks, trigger runs, and verify inbound webhooks from Node, Next.js, Express, and other JavaScript frameworks.


What problem does it solve?

Building async agent workflows usually means stitching together:

  • A job queue and scheduler
  • LLM calls with tool use (fetch URL, parse HTML, compare state)
  • Webhook delivery and retry logic
  • Change detection between runs

Meerkat handles all of that as a managed API. meerkat-js handles the client side:

Without the package With meerkat-js
Raw fetch calls Typed client methods (client.tasks.create, client.tasks.run)
Manual auth headers API key configured once
DIY webhook HMAC verification verifyWebhook() + Express/Next helpers
snake_case JSON by hand camelCase API with automatic wire-format conversion

Why use this package?

  • Webhook-native — every task delivers JSON to your endpoint; verify signatures with built-in helpers
  • BYOK — Anthropic, OpenAI, OpenRouter, or Grok; keys stored on your Meerkat account
  • Recurring + one-off — natural-language schedules (every 2 hours) or ad-hoc runs
  • Self-host or Cloud — same API against Docker, Render, Fly.io, or Meerkat Cloud
  • Framework entry pointsmeerkat-js/express and meerkat-js/next for webhook handlers

How it works

┌─────────────┐     client.tasks.create   ┌─────────────┐     agent + tools    ┌─────────────┐
│  Your app   │ ───────────────────────►  │   Meerkat   │ ──────────────────►  │  Web / APIs │
└─────────────┘                           └─────────────┘                      └─────────────┘
       ▲                                          │
       │              POST output_webhook         │
       └──────────────────────────────────────────┘
              (verify with verifyWebhook)
Step What happens
1. Register client.tasks.create(...) — describe work, pass params, set webhook
2. Run Meerkat schedules recurring tasks or runs one-offs on demand
3. Receive Findings POSTed to your webhook as structured JSON

Use cases

What teams ship with Meerkat — aligned with the use cases on meerkatagents.com:

Use case In one line On the website
Package tracking Webhook when DHL, UPS, FedEx, or any carrier status changes Package tracking →
Website monitoring Watch a URL; get notified when the signal you describe happens Site monitoring →
Price & stock Competitor price drops and restocks without building a scraper Guide →
Async agent webhooks Register LLM agent work; results POST to your endpoint Agent webhooks →

Read the full developer guides for step-by-step tutorials with API examples.


Package tracking — webhook when status changes

Monitor any courier tracking link — DHL, UPS, FedEx, USPS, DPD, Royal Mail — with one API. Meerkat's agent reads the carrier page on a schedule, detects state changes, and POSTs structured JSON to your endpoint. No per-carrier SDKs, no polling loops, no LLM tool code to maintain.

  • Every carrier, one endpoint — pass a courier_tracking_link; adding a new carrier is zero integration code.
  • Webhook on change only — hear from Meerkat when status moves (In transit → Out for delivery → Delivered), not on every poll.
  • Signed and retried — HMAC-SHA256 signatures, exponential backoff, delivery history via the events API.
await client.tasks.create({
  taskType: "recurring",
  description: "Monitor DHL tracking and report status changes",
  inputParams: { courier_tracking_link: "https://www.dhl.de/track?id=..." },
  frequency: "every 2 hours",
  outputWebhook: "https://your-app.com/webhooks/meerkat",
});

Package tracking use case · Shipment tracking guide


Website monitoring — watch any URL

A change-detection API that understands intent, not just pixel diffs. Describe the signal in plain English — price under $99, plan name changed, status page updated — and Meerkat watches on a schedule. It only fires your webhook when that condition is met.

  • Semantic, not cosmetic diff — no CSS selectors to maintain when the page layout shifts.
  • JS-rendered pages — SPAs and dynamic content via headless fetch before reasoning.
  • Your schedule — natural language (every 15 minutes), cron, or on-demand client.tasks.run(id).
await client.tasks.create({
  taskType: "recurring",
  description: "Notify me when this product drops below $99",
  inputParams: { url: "https://shop.example.com/widget-pro" },
  frequency: "every 30 minutes",
  outputWebhook: "https://your-app.com/webhooks/meerkat",
});

Website monitoring use case · Monitor website for changes guide


Price & stock monitoring — competitor alerts

Track competitor product pages and get a signed webhook when price drops, price increases, or stock flips (out of stock → in stock). One task per SKU — no scraper fleet, scheduler, or retry layer to operate.

await client.tasks.create({
  taskType: "recurring",
  description: "Report price and stock whenever either changes",
  inputParams: { url: "https://competitor.com/product/sku-123" },
  frequency: "every 15 minutes",
  outputWebhook: "https://your-app.com/webhooks/meerkat",
});

Example webhook when price moves:

{
  "data": {
    "summary": "Price dropped from 99.00 to 89.00",
    "findings": { "price": 89.0, "previous_price": 99.0, "in_stock": true },
    "change_detected": true
  }
}

Competitor price & stock guide


Async agent webhooks — skip the scheduler boilerplate

Meerkat is the open source primitive for engineers who would rather ship product than rebuild schedulers, LLM tool loops, retries, and signed webhook delivery. Register a task in plain English, attach your LLM key (BYOK), point at an endpoint — done.

  • One verb: registerPOST /tasks creates recurring or one-off agent work.
  • Webhook-native results — structured JSON, signed, retried until 2xx (same contract as Stripe or GitHub webhooks).
  • MIT & self-hostable — Docker, Render, Fly.io, or Meerkat Cloud; identical REST API.
await client.tasks.create({
  taskType: "recurring",
  description: "Summarize new arXiv papers in distributed systems",
  inputParams: { topic: "distributed systems" },
  frequency: "0 9 * * *",
  outputWebhook: "https://your-app.com/webhooks/meerkat",
});

Agent webhooks use case · Webhook vs polling guide


One-off lookups

Ad-hoc agent tasks without standing up a schedule — research, single URL extraction, or on-demand runs from your API routes:

await client.tasks.create({
  taskType: "one_off",
  description: "Fetch the current price of this product once",
  inputParams: { url: "https://example.com/product/123" },
  outputWebhook: "https://your-app.com/webhooks/meerkat",
});

Scheduled scraping with webhooks

Need data on a cadence, not just change detection? Set a frequency and receive structured findings every run — see the web scraping API guide.


Task types

Type Behavior Best for
recurring Runs on a schedule; compares state between runs; reports changes Courier tracking, uptime, price watches
one_off Runs once, reports findings, marks task complete Ad-hoc research, single lookups

Frequency accepts natural language (every 30 minutes, hourly, every 2 hours) or cron expressions. Required for recurring tasks; omit for one_off.


Self-host vs Meerkat Cloud

Self-host (OSS) Meerkat Cloud
API Identical Identical
LLM keys You supply (BYOK) You supply (BYOK)
Infra / ops You run Postgres + workers Managed for you
Base URL http://localhost:3000/api/v1 https://cloud.meerkatagents.com/api/v1 (default)

LLM usage is always billed by your provider. Meerkat never sees your model costs.

Self-host: meerkat README — Docker


Installation

npm install meerkat-js

Quick start

1. Get an API key

Sign up via the Meerkat Cloud dashboard or programmatically:

import { MeerkatClient } from "meerkat-js";

const signupClient = new MeerkatClient({ baseUrl: "https://cloud.meerkatagents.com/api/v1" });
const result = await signupClient.signup.create({ email: "you@company.com", name: "Your Name" });
const apiKey = result?.data.apiKey; // store securely — shown once

2. Create a task

import { MeerkatClient } from "meerkat-js";

const client = new MeerkatClient({ apiKey: process.env.MEERKAT_API_KEY! });

const { data: task } = await client.tasks.create({
  taskType: "recurring",
  description: "Monitor courier tracking and notify on status changes",
  inputParams: { courier_tracking_link: "https://..." },
  frequency: "every 2 hours",
  outputWebhook: "https://your-app.com/webhooks/meerkat",
});

3. Trigger a run (optional)

await client.tasks.run(task.id, { async: true });

Examples

List and manage tasks

await client.tasks.list({ status: "active", taskType: "recurring", limit: 20 });
await client.tasks.retrieve(1);
await client.tasks.update(1, { description: "Updated description" });
await client.tasks.pause(1);
await client.tasks.resume(1);
await client.tasks.delete(1);

One-off lookup

await client.tasks.create({
  taskType: "one_off",
  description: "Fetch the current price of this product",
  inputParams: { url: "https://example.com/product/123" },
  outputWebhook: "https://your-app.com/webhooks/meerkat",
});

Inspect runs and webhook delivery history

await client.tasks.runs(1, { limit: 10 });
await client.tasks.events(1, { limit: 50 });

API keys

await client.apiKeys.list();
await client.apiKeys.create({ name: "Production" });
await client.apiKeys.revoke(keyId);

Receiving webhooks

Every outbound POST is HMAC-SHA256 signed in the X-Meerkat-Signature header.

import { verifyWebhook } from "meerkat-js";

verifyWebhook({
  payload: rawBody,
  signature: req.headers["x-meerkat-signature"],
  secret: process.env.MEERKAT_WEBHOOK_SECRET!,
});

Express

Capture the raw body, then use the middleware:

import express from "express";
import { meerkatWebhookMiddleware } from "meerkat-js/express";

const app = express();

app.post(
  "/webhooks/meerkat",
  express.raw({ type: "application/json" }),
  (req, _res, next) => {
    req.rawBody = req.body;
    next();
  },
  meerkatWebhookMiddleware({ secret: process.env.MEERKAT_WEBHOOK_SECRET! }),
  (req, res) => {
    const payload = JSON.parse(String(req.rawBody));
    res.json({ ok: true });
  },
);

Next.js App Router

import { verifyNextWebhook } from "meerkat-js/next";

export async function POST(request: Request) {
  const valid = await verifyNextWebhook({
    request,
    secret: process.env.MEERKAT_WEBHOOK_SECRET!,
  });
  if (!valid) return new Response("Unauthorized", { status: 401 });
  return Response.json({ ok: true });
}

Output formats

outputWebhook is required on every task (or use "default" if your account has a default webhook configured). outputFormat is optional.

Preset Webhook payload shape
default { event, task_id, task_run_id, occurred_at, data: { summary, findings, change_detected, ... } }
compact Top-level summary, change_detected, findings
flat Findings merged into the webhook root object
findings_only Findings object only
minimal event, task_id, summary, change_detected
await client.tasks.create({
  description: "...",
  inputParams: { url: "https://..." },
  outputWebhook: "https://your-app.com/hook",
  outputFormat: "flat",
});

Any other string is passed to the agent as a custom instruction for shaping findings (max 500 chars).


API reference

Default base URL: https://cloud.meerkatagents.com/api/v1

All endpoints except signup require Authorization: Bearer mk_....

The client uses camelCase in TypeScript; requests are converted to snake_case automatically.

SDK method HTTP Description
client.signup.create(...) POST /signup Create account + API key
client.apiKeys.list() GET /api_keys List API keys
client.apiKeys.create({ name }) POST /api_keys Generate a new key
client.apiKeys.revoke(id) DELETE /api_keys/:id Revoke a key
client.tasks.list(...) GET /tasks List tasks
client.tasks.create(...) POST /tasks Create a task
client.tasks.retrieve(id) GET /tasks/:id Task details + last known state
client.tasks.update(id, ...) PATCH /tasks/:id Partial update
client.tasks.replace(id, ...) PUT /tasks/:id Full replace
client.tasks.delete(id) DELETE /tasks/:id Archive or delete
client.tasks.run(id, { async }) POST /tasks/:id/run Trigger on-demand run
client.tasks.pause(id) POST /tasks/:id/pause Pause recurring task
client.tasks.resume(id) POST /tasks/:id/resume Resume recurring task
client.tasks.runs(id) GET /tasks/:id/runs Run history
client.tasks.events(id) GET /tasks/:id/events Webhook delivery log

Full OpenAPI spec: meerkat/openapi/openapi.yaml


Configuration

Environment variables

Variable Description
MEERKAT_API_KEY API key from signup (mk_...)
MEERKAT_BASE_URL API base URL (default: Meerkat Cloud)
MEERKAT_WEBHOOK_SECRET Secret for verifying inbound webhooks

Client options

const client = new MeerkatClient({
  apiKey: process.env.MEERKAT_API_KEY,
  baseUrl: "http://localhost:3000/api/v1", // self-hosted
  timeoutMs: 30_000,
  fetch: customFetch, // optional custom fetch impl
});

Development

npm install
npm run build
npm test

See PUBLISHING.md for npm release steps.


Related projects


License

MIT — see LICENSE.

About

Official JavaScript/TypeScript SDK for Meerkat (npm: meerkat-js)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages