Riveter

io.github.CodyWattersPublished by GitHub account CodyWattersv0.3.6Updated Nov 3, 2026

MCP server for Riveter's enrichment, scraping, and monitoring API

Overview

AI-generated overview

Riveter's MCP server lets an assistant build datasets, enrich rows with AI-researched columns, scrape pages, search the web, and schedule monitors.

What you can do
  • Build and manage datasets: create, update, delete, import CSV rows, edit rows, promote columns, export to CSV or JSON Lines, and summarize column values
  • Enrich rows with AI-researched output columns, create and edit enrichment recipes, and list available agent tools
  • Run and track async jobs: list runs, check status and progress, fetch results, stop runs, and view run summaries
  • Scrape webpages, run synchronous web searches, and ask one-off research questions
  • Create reusable website extractions and run them to get structured records
  • Set up monitors that refill dataset columns on a schedule and deliver results or changes to a webhook
When to use it
Useful when you want an assistant to turn a list of companies, people, or other entities into an enriched table, pull structured records from websites, or keep a dataset refreshed on a schedule without leaving the chat.
Requirements
Either the hosted endpoint with OAuth sign-in in a browser, or the local npm package run with npx, which needs Node.js and the RIVETER_API_KEY environment variable. Clients that cannot open a browser can pass an Authorization bearer header instead. A Riveter account is required.
Before you install
Several operations are paid in Riveter credits, including generated rows, enrichments, extractions, and searches; use the cost-estimate option and a credit cap before running them. Tools can create, modify, and delete datasets, rows, enrichments, and monitors, and stopping a run is irreversible. Monitors can POST results to a webhook URL you supply. The API key grants access to the whole account, so keep it out of shared configs and revoke it to disconnect a client.

Installation

In SourceWeft

  1. Open Riveter in the dashboard and add it to a workspace.
  2. Connect the required credentials. They are stored privately and never shown on public pages.
  3. Enable the server for the chats that should use its tools.

Web executable via Streamable HTTP. Remote servers run from the web runtime once configured in a workspace.

Use with an agent

Paste this prompt into Claude Code, Codex, Cursor or another agent — or into SourceWeft chat. The agent reads this server's install guide, shows you its publisher, endpoint and sign-in, and adds it to your client once you agree. Keys never go into a command.

Read https://sourceweft.com/mcp/io.github.CodyWatters%2Friveter/install.md and connect the MCP server it describes to my client. Before changing any config, show me its publisher, endpoint and sign-in method and wait for my OK. Never put an API key in a command or in a file I would commit; ask me where it should come from.

Read the install guide the agent follows

Other MCP clients

Add this to your client's mcpServers config. The client completes OAuth sign-in on first connect.

{
  "mcpServers": {
    "riveter": {
      "type": "http",
      "url": "https://mcp.riveterhq.com/mcp"
    }
  }
}

README

Riveter MCP Server

An MCP (Model Context Protocol) server that connects AI assistants like Claude and Cursor to the Riveter API. Run enrichments, build datasets, scrape webpages, manage monitors, and more — directly from your assistant.

Tools are generated dynamically from Riveter's OpenAPI spec, so they stay up to date automatically.

Two ways to connect:

  • Hosted — https://mcp.riveterhq.com/mcp. Nothing to install. Works from claude.ai, Claude Desktop, Cowork, Claude mobile, ChatGPT, Claude Code, and Cursor.
  • Local (npx) — this npm package, run on your machine over stdio. Use it when your client cannot reach remote servers.

Setup

1a. Hosted server (no API key needed up front)

Add https://mcp.riveterhq.com/mcp as a custom connector and click Connect. A browser window opens on Riveter: sign in and click Allow. Riveter creates an API key for that connection; it is listed in Settings → API keys, and revoking it disconnects the client.

Claude Code:

bash
claude mcp add --transport http riveter https://mcp.riveterhq.com/mcp

Then run /mcp and choose Authenticate.

Cursor:

json
{  "mcpServers": {    "riveter": {      "url": "https://mcp.riveterhq.com/mcp"    }  }}

If the client cannot open a browser, pass a key as a header instead: Authorization: Bearer sk_riv_your_key_here (Claude Code --header "Authorization: Bearer sk_riv_...", Cursor "headers": { "Authorization": "Bearer sk_riv_..." }).

1b. Local server (npx)

Get a Riveter API key at app.riveterhq.com/settings/api.

Claude Desktop — open the config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Add the Riveter server:

json
{  "mcpServers": {    "riveter": {      "command": "npx",      "args": ["-y", "--prefer-online", "riveter-mcp-server@latest"],      "env": {        "RIVETER_API_KEY": "sk_riv_your_key_here"      }    }  }}

Cursor / Windsurf — add the same riveter entry to your MCP config (e.g. ~/.cursor/mcp.json).

Claude Code:

bash
claude mcp add riveter --env RIVETER_API_KEY=sk_riv_your_key_here -- npx -y riveter-mcp-server

Codex:

bash
codex mcp add riveter --env RIVETER_API_KEY=sk_riv_your_key_here -- npx -y riveter-mcp-server

Keeping the tools current: the local server loads the API definition once, when your client starts it, and keeps that process running. After Riveter ships an API change, restart your AI client (or the MCP server from its settings page) to load the new tools. --prefer-online riveter-mcp-server@latest makes the same restart also pick up new server versions. The hosted server needs no restart; it reloads the API definition every 10 minutes.

Environment variables

Local (stdio) server — dist/index.js:

VariableRequiredDefaultDescription
RIVETER_API_KEYYes—Your Riveter API key
RIVETER_API_BASE_URLNohttps://api.riveterhq.com/v1API base URL
RIVETER_OPENAPI_URLNohttps://docs.riveterhq.com/openapi.yamlOpenAPI spec URL. https://docs.riveterhq.com/openapi.legacy.yaml serves the legacy generation instead (verb endpoints, legacy enrichments, the retired list-build operations)

Hosted (Streamable HTTP) server — dist/http.js, deployed by Riveter:

VariableDefaultDescription
PORT8080Listen port
MCP_PUBLIC_URLhttps://mcp.riveterhq.com/mcpPublic URL, exactly as users enter it (RFC 9728 resource)
OAUTH_ISSUER_URLhttps://app.riveterhq.comAuthorization server advertised in the protected resource metadata
SPEC_REFRESH_INTERVAL_MS600000How often the spec is re-fetched; 0 disables
RIVETER_API_BASE_URL, RIVETER_OPENAPI_URLas above

The hosted server holds no API key. It forwards the caller's Authorization: Bearer ... header to the API on every call and answers 401 with a WWW-Authenticate challenge when the header is missing.

How it works

On startup, the server:

  1. Fetches the OpenAPI spec from docs.riveterhq.com/openapi.yaml
  2. Parses each endpoint into an MCP tool with typed parameters and annotations (readOnlyHint from GET, destructiveHint from DELETE or the spec's x-mcp-destructive, openWorldHint from the spec's x-mcp-open-world)
  3. Uses the spec's info.x-mcp-instructions as the short server-level instructions (the long API overview stays on the docs site); an operation's x-mcp-description replaces its description for the tool when set
  4. Adds one help tool whose topics (column config, formats, tools, run_when, examples, credits, limits, errors, ...) come from the spec's info.x-mcp-help — long guidance is loaded only when the assistant asks for it
  5. Serves the tools over stdio (local) or Streamable HTTP (hosted)

When the API docs are updated, the local server picks up the changes the next time your assistant launches, and the hosted server re-fetches the spec every 10 minutes — no rebuild or republish needed.

Development

Source: github.com/riveterhq/riveter-mcp. Issues welcome there.

bash
npm installnpm test          # build + unit + stdio e2e + http e2enpm run dev:http  # hosted server on :8080 (set MCP_PUBLIC_URL=http://localhost:8080/mcp)

This repository is a read-only mirror of the mcp-server/ directory of Riveter's private monorepo, where development happens. The spec-contract tests need the monorepo's openapi.yaml, so they skip here. Releases are described in PUBLISHING.md.

Support

Questions or issues? See the Riveter API docs or contact [email protected].

License

MIT

Source: README.md at commit 4c129a2

Tools

40

enrich

Enrich

enrich Add AI-researched columns to rows. Rows come from exactly one of `dataset_id` (`ds_...`, preferred) or `input` (inline, columnar: `{ "Header": ["row1", "row2"] }`, all arrays equal length; a one-off, nothing kept). Preferred: put the rows in a dataset first (`build_dataset` with `rows` + `attributes` or `enrichment_id`, free; it keeps the rows and filled cells), then `enrich` with its `dataset_id`: fills its cells with its enrichment; no column config needed. Default scope: every `pending`, `stale`, or `failed` cell; `columns`, `rows`, `positions` narrow it; `force: true` re-runs filled cells. `prompt` + `attributes` fills the named columns, adding the missing ones first; `output` is refused (`update_dataset` sets a column's prompt / schema / tool). `help` with `datasets`. With `input`, column config is exactly one of, most consistent first: 1. `enrichment_id` — a saved enrichment (`enr_...`, `list_enrichments`): fixed, tested config; up to 10,000 rows; input headers must match its input columns (`get_enrichment`). 2. `prompt` + `attributes` — the task and up to 20 column names; no setup; up to 1,000 rows. 3. `output` — per column `prompt`, optional `output_schema`, optional pinned `tool`; up to 1,000 rows. `help` with `column_config` or `examples` first. Returns a run. Poll `get_run_result` with `wait: 50` (or pass `webhook_url`); a dataset fill's result is `{ "rows": [...] }`, only the rows it ran. `estimate_cost: true` prices it without running. A `legacy` key in the response means the call took a legacy mode (a legacy enrichment's id, legacy-pipeline column fields); follow `legacy.successor`. **Example — Run a saved enrichment:** { "enrichment_id": "enr_018f5b60-1234-7abc-89ab-0123456789ab", "input": { "Company Name": [ "Acme Corp", "Tech Solutions Inc" ] } } **Example — Prompt + attributes (a task and column names):** { "prompt": "Research each company", "attributes": [ "CEO", "Employee Count", "Industry"

Parametersrowsforceinputoutputpromptstatescolumnsrun_keytargetspositionsattributesdataset_id+5 more

get_run

Run status

run status This returns the **status and progress** of a run for any run created from enrichments, datasets, or extractions. `status` reports the status of the run, and `progress` gives a completion estimate. `?wait=N` (max 50) long-polls: the request holds until the run finishes or the budget elapses. **Workflow:** Pass `wait` (seconds, max 50) to hold the request until the run finishes; repeat until `status` is 'success' or 'stopped'.

Parametersidrequiredwait

get_run_result

Run result

run result The run plus `output`, `null` until the run finishes. Pass `?wait=N` (max 50) to long-poll: the request holds until the run finishes or the budget elapses, whichever comes first. ## Output shape by run type - **enrichment** — an object mapping column headers to arrays of cell objects: `{ "Company": [{"value": "Apple"}], "CEO": [{"value": "Tim Cook"}] }` - **dataset_build** — the same columnar shape as enrichment - **extraction** — the extracted records as an array of JSON objects (matching your `output_record_json_schema`) - **quick_search** — the search result object `{ "results": [{ "title", "link", "snippet" }, ...], "knowledge_graph"? }`, the same data the synchronous `POST /quick_search` response already carried. (Runs started on the legacy async `/web_search` endpoint share this run type but return the columnar enrichment shape with a `search_results` column.) - **search_agent** — the answer object `{ "result": <string or object> }`; `result` matches the request's `output_schema` when one was given, otherwise it's free text. - **enrichment** on a dataset (`POST /enrich` with `dataset_id`) — `{ "rows": [...] }`: only the rows the fill ran, in position order, each in the `/datasets/{id}/rows` shape (`id`, `position`, `input`, `cells` limited to the columns the fill covered, `credits`). `GET /datasets/{id}/rows` is the live view. Above 5,000 rows, or after the rows expire (30 days), `output` is `null` and `output_files` (signed CSV and JSONL links to the whole grid; `pending` until the export lands, valid one hour, see `expires_at`) are the output. - **enrichment** started on `POST /enrich_rows`, or on `POST /enrich` with `input` — the columnar shape while rows are ≤ 5,000, plus the same `output_files`. Above 5,000 rows, or after the rows expire (30 days), `output` is `null` and the files are the output. **Workflow:** `output` is null until the run finishes. Pass `wait` (seconds, max 50) to long-poll instead of sleeping between calls.

Parametersidrequiredwait

stop_run

Stop run

stop run Stop a run early. Works for every run type. Already-finished runs are left untouched; the response is the run either way. **Workflow:** Stops a running run. The run cannot be resumed after stopping.

Parametersidrequired

list_runs

List runs

list runs List the account's runs, newest first. Every async operation shows up here — enrichment runs, dataset builds, extractions, and quick searches. Filter by `type` (comma-separated), `status`, `enrichment_id`, `dataset_id`, `monitor_id`, and `created_after` / `created_before` (ISO 8601). Paginate with `page` / `per_page`. `enrichment_id` naming a legacy enrichment still filters and the response carries `legacy`. Pass `ids` (comma-separated, up to 100 run ids) to get those runs' full status objects (same shape as `GET /runs/{id}`) in one call; `not_found` lists ids not on this account. Filters and pagination are ignored.

Parametersidspagetypestatusper_pagedataset_idmonitor_idcreated_afterenrichment_idcreated_before

runs_summary

List runs (summary)

list runs (summary) All-time run counts by status — a snapshot of the account's run queue. For the runs themselves use [GET /runs](#tag/runs/get/runs)`?status=...`.

Takes no parameters.

get_enrichment

Read enrichment

read enrichment One enrichment by id: `prompt`, `input_columns` (the headers rows must carry), `output` columns (`name`, `prompt`, `output_schema`, a pinned `tool` when the column is one tool call), `tools`, `budget_credits_per_row`, `version`. A `legacy` key means the id is a legacy enrichment's; its `successor` names the dataset copy.

Parametersidrequired

update_enrichment

Update enrichment

update enrichment Edit an enrichment: `name`, `prompt`, `input_columns`, `budget` (credits per row; moves by 1.5 per output column added or removed unless `budget_locked`), `only_tools` / `additional_tools`, and `output` columns by name: a new name adds a column (type inferred unless `output_schema` is given), `{ "prompt", "output_schema" }` changes one, `{ "tool": "<list_tools name>" }` pins a tool to it — one call per row is the cell, the agent choosing the arguments (`null` unpins; `help` with `pinned_columns`), `{ "rename" }` renames, `{ "delete": true }` removes. Changed columns make dataset cells `stale` (re-run by the next `enrich`). 409 `enrichment_in_use` while a fill runs. Prefer `update_dataset` to change one dataset's columns. `help` with `output_schema`. **Example — Change one column's prompt, add a typed one:** { "output": { "CEO": { "prompt": "Full name of the current CEO" }, "Employee count": { "prompt": "Current headcount as an integer", "output_schema": { "type": "integer", "minimum": 0 } } } } **Example — Rename a column, delete another:** { "output": { "HQ": { "rename": "HQ city" }, "Old Column": { "delete": true } } } **Example — New prompt and budget:** { "prompt": "Research each company's go-to-market motion", "budget": 8 }

Parametersidrequirednamebudgetoutputpromptonly_toolsbudget_lockedinput_columnsadditional_tools

delete_enrichment

Delete enrichment

delete enrichment Delete an enrichment by id. Runs in flight finish; a dataset bound to it keeps its columns. A legacy enrichment's id is refused (422 with `legacy`); those are deleted in the app.

Parametersidrequired

list_enrichments

List enrichments

list enrichments The account's enrichments, newest first: id, name, input / output column names. A legacy enrichment's item also has `status`, `app_url`, and `dataset_id` (its dataset copy: `enrich` that instead). Paginate with `page` / `per_page` (max 50); filter by `status` (legacy only), `name`. `get_enrichment` has the columns' config.

Parametersnamepagestatusper_page

create_enrichment

Create enrichment

create enrichment Create an enrichment (no run, free) and the empty dataset it fills, bound to it and in the app at `app_url`. A recipe: `prompt` (the task), `output` columns (names, or `{ name, prompt, output_schema, tool }` — `tool: "<list_tools name>"` pins a tool: one call per row, arguments chosen by the agent, result is the cell; `help` with `output_schema` / `pinned_columns`), optional `input_columns`, `budget` (credits per row, default 1.5 per output column; follows column adds / removes unless `budget_locked`), `only_tools` / `additional_tools` (`list_tools`). Prefer `prompt` alone: the output columns (one typed column per fact asked for), name, and input columns are written from it; the response shows them. Then `add_dataset_rows` to the `dataset_id` and `enrich` with it (preferred), or `enrich` with `enrichment_id` + `input` for a one-off. `dataset_id` alone answers a dataset's own enrichment as `{ id, name, app_url, dataset_id }` (422 without output columns; add them with `update_dataset`). **Example — Save a recipe — three columns, one typed:** { "name": "Company basics", "prompt": "Research each company from its name and website.", "input_columns": [ "Company", "Website" ], "output": [ "CEO", { "name": "Employee count", "prompt": "Current headcount as an integer", "output_schema": { "type": "integer", "minimum": 0 } }, { "name": "Summary", "prompt": "Two sentences on what the company sells and to whom" } ], "budget": 4 } **Example — The recipe written from the prompt — columns, name, and input columns:** { "prompt": "Research each company from its name and website: the CEO, employee count, latest funding round date and amount, and whether it is hiring." } **Example — A dataset's own enrichment:** { "dataset_id": "ds_018f6a70-1234-7abc-89ab-0123456789ab" }

Parametersnamebudgetoutputpromptdataset_idonly_toolsbudget_lockedinput_columnsadditional_tools

list_datasets

List datasets

list datasets The account's datasets, newest first (up to 200): id, name, column counts, `row_count`, newest run. `get_dataset` has the columns and enrichment.

Takes no parameters.

build_dataset

Build dataset

build dataset Build a dataset: rows you send or rows Riveter finds. `rows` (≤ 100 objects keyed by input column name, free) or `prompt` + `count` (generated, paid); output columns from `attributes` or `enrichment_id`, or, with `prompt` + `count` alone, written from the prompt (one typed column per fact it asks for) along with the identity columns; `auto_fill: true` fills generated rows when they land; `budget` caps a generation's spend (default 50 + 1.5 per row; deposit of expected charged now, rest as it runs). Returns the dataset (`id`, `ds_...`) and `run` (the generation run, or null); then `enrich` with `dataset_id` alone. `estimate_cost: true` prices it first. `help` with `datasets`. **Example — Rows you have, two columns to fill:** { "name": "Targets", "rows": [ { "Company": "Apple", "Website": "apple.com" }, { "Company": "Shopify" } ], "attributes": [ "CEO", "HQ city" ] } **Example — Generate 50 rows on a 100-credit budget, filled when they land, refused above 200 credits:** { "prompt": "Specialty coffee roasters in San Francisco", "count": 50, "input_columns": [ "Roaster", "Website" ], "attributes": [ "Founded year" ], "auto_fill": true, "budget": 100, "max_credits": 200 } **Example — The whole dataset from the prompt — identity columns and typed output columns:** { "prompt": "Top 50 US fintech startups with their CEO, total funding, and founding year", "count": 50, "auto_fill": true } **Workflow:** The response is the dataset and, with `prompt` + `count`, a generation `run` — poll it with `get_run`, then read the rows with `list_dataset_rows` (`auto_fill: true` researches them as they land).

Parametersnamerowscountbudgetpromptauto_fillattributesmax_creditswebhook_urlenrichment_idestimate_costinput_columns+1 more

get_dataset

Read dataset

read dataset One dataset by id: `input_columns`, `index_column`, `enrichment_id` + `output_columns` (names; `get_enrichment` has the prompts), `row_count`, `import_in_progress`, newest `runs`. Rows are `list_dataset_rows`.

Parametersidrequired

update_dataset

Update dataset

update dataset Edit a dataset's structure (no run): `name`; `index_column`; `input_columns` ops (`{ "Name": {} }` add, `{ "rename" }`, `{ "delete": true }`); `output` column ops (new name adds, type inferred unless `output_schema` is given; `{ "prompt", "output_schema" }` changes, cells go `stale`; `{ "tool": "<list_tools name>" }` pins a tool: one call per row, arguments chosen by the agent, result is the cell (`null` unpins); `{ "rename" }`; `{ "delete": true }`); `budget` (credits per row; moves by 1.5 per output column added or removed unless `budget_locked`) and `budget_locked` (true / false; sent with column changes it wins over that adjustment). Edits a shared enrichment on a private copy. 409 `dataset_in_use` while a fill runs. Then `enrich` with `dataset_id`. `help` with `datasets`, `pinned_columns`, `output_schema`. **Example — Change a prompt, add a typed column, remove one:** { "output": { "CEO": { "prompt": "Full name of the current CEO" }, "Employee count": { "prompt": "Current headcount as an integer", "output_schema": { "type": "integer", "minimum": 0 } }, "HQ city": { "delete": true } } } **Example — Lock the budget and add columns without moving it:** { "budget_locked": true, "output": { "Founded": {}, "Revenue": { "prompt": "Latest annual revenue in USD" } } } **Example — A column pinned to the LinkedIn profile lookup; the agent finds the URL to call it on:** { "output": { "Profile": { "prompt": "The LinkedIn profile of the row's person; find the canonical linkedin.com/in/<slug> URL first", "tool": "linkedin_person_profile" } } } **Example — Rename the dataset, add an input column and dedupe on it, rename another:** { "name": "Q4 targets", "input_columns": { "Ticker": {}, "Website": { "rename": "Domain" } }, "index_column": "Ticker" }

Parametersidrequirednamebudgetoutputindex_columnbudget_lockedinput_columns

delete_dataset

Delete dataset

delete dataset Delete a dataset by id (rows and cells with it; its enrichment stays). 409 `dataset_in_use` while a run is on it.

Parametersidrequired

list_dataset_rows

List rows

list rows Rows of a dataset in position order: `input` by column name, `cells` by output column name (`value`, `state`: pending / running / ok / not_found / failed / manual / stale, `reason` + `error` on failed), `credits` and `not_found_reason` per row. `limit` up to 1,000; pass `next_cursor` back as `cursor` for the next page; `updated_since` for changes only. To read a whole dataset: `columns` names the columns, `compact: true` makes rows `{ position, input, cells: { "<column>": value } }`; 1,000 rows of one column is one call. For counts of a column's values or states, `get_dataset_summary`.

Parametersidrequiredlimitcursorcolumnscompactupdated_since

add_dataset_rows

Add rows

add rows Append up to 100 rows (objects keyed by input column name; free). Duplicates on the index column are skipped (`skipped_duplicates`). Returns the inserted rows. Then `enrich` with `dataset_id`. More rows: `import_dataset_rows`.

Parametersidrequiredrowsrequired

delete_dataset_rows

Delete rows

delete rows Remove rows: `ids` (comma-separated `row_...` ids) and / or `positions` (comma-separated positions from 1), up to 100 rows together. Returns the number deleted.

Parametersidrequiredidspositions

import_dataset_rows

Import rows (CSV)

import rows (CSV) Append rows from CSV text (`csv`; header row = input and / or output column names, output values land as `manual` cells; free). Up to 1,000 rows land at once (`import.status` done); more are accepted and land in the background (`importing`; `get_dataset` shows `import_in_progress`). Duplicates on the index column are skipped.

Parametersidrequiredcsvrequired

build_dataset_rows

Generate more rows

generate more rows Generate `count` more rows for a dataset (paid; `estimate_cost` first). Needs a `index_column` on the dataset (`update_dataset`). `prompt` says what to find (default: the dataset's last build prompt); the generator skips the existing rows and may find fewer than `count` — the finished run's `progress` has `requested_rows`, `generated_rows`, `added_rows`, `skipped_duplicate_rows`. `auto_fill: true` fills them when they land. Returns the dataset and `run`. **Example — Fifty more, filled on arrival:** { "prompt": "Specialty coffee roasters in Oakland and Berkeley", "count": 50, "auto_fill": true }

Parametersidrequiredcountrequiredbudgetpromptauto_fillmax_creditswebhook_urlestimate_costfill_webhook_url

update_dataset_row

Set input values

set input values Write one row (`row_id`: a `row_...` id or a position) by hand. `input` is `{ "<input column>": value | null }` (an index-column value another row holds is a 422). `cells` is `{ "<output column>": value | null }`: a value becomes a `manual` cell (kept by fills unless `force`); `null` clears it back to `pending`. One write for both. 409 `row_in_use` for `input` while a fill is on the row; `cells` land meanwhile and stand over the run's answer.

Parametersidrequiredcellsinputrow_idrequired

promote_dataset_column

Convert output column to input

convert output column to input Make a filled output column an input column of the same name (`column`); every row's value moves with it, so later columns and dedupe can key on it. Not undoable; 409 `dataset_in_use` while a fill runs.

Parametersidrequiredcolumnrequired

export_dataset

Export dataset (CSV, Excel, or JSON Lines)

export dataset (CSV, Excel, or JSON Lines) The dataset as CSV text (or JSON Lines with `output_format: "jsonl"`; `xlsx` is binary and meant for a browser): input columns, then output columns, one line per row. For a few rows prefer `list_dataset_rows` (it carries cell states); for a whole dataset, `list_dataset_rows` with `columns` + `compact`; for counts, `get_dataset_summary`.

Parametersidrequiredoutput_format

get_dataset_summary

Summarize columns

summarize columns Counts over every row of a dataset, no rows read: per column, `states` (an output column's cells: pending / stale / failed / not_found / ok / manual), `filled`, `distinct_values`, and `values` (the `top_values` most common as `{ value, count }`, default 20, max 100; strings cut at 200 characters). The call for "how many of each", "how many are not found", "what does this column hold", and what a fill filled. `columns` picks the columns; absent, all.

Parametersidrequiredcolumnstop_values

build_configured_dataset

Build configured list

build configured list Run a **configured list build** — a reusable, pre-configured list template (id `cds_...`) set up for your account ("Configured list builds" in the app). The spec, prompt template, row cap, and per-run credit cost are all defined on the template; you only supply `parameters` to fill in its `{{ placeholder }}` values. Returns the list-build run; poll [GET /runs/{id}](#tag/runs/get/runs/{id}). The rows land in a dataset named by the run's `dataset_id`; fill them with [POST /enrich](#tag/enrich/post/enrich). **Example — Fill in template parameters:** { "parameters": { "practice_type": "dentists", "state": "ohio" } } **Workflow:** Starts an async run of a configured list build. Poll `get_run`; the rows land in the dataset the run's `dataset_id` names (`list_dataset_rows`), then `enrich` with it.

Parametersidrequiredtierparametersmax_creditsestimate_costdataset_webhook_url

run_extraction

Run extraction

run extraction Execute a `ready` extraction. Returns a run — poll [GET /runs/{id}](#tag/runs/get/runs/{id}) and fetch the extracted records with [GET /runs/{id}/result](#tag/runs/get/runs/{id}/result) (the records come back as an array of JSON objects matching your schema), or pass a `webhook_url`. `variables` fills any `{{ placeholder }}` values the plan defines (e.g. a search term or location). Each run charges run credits (`credits_charged`). **Workflow:** Starts an async extraction run. Poll `get_run`, then fetch the records with `get_run_result`.

Parametersidrequiredvariablesmax_creditswebhook_urlestimate_cost

create_extraction

Create extraction

create extraction Create an **extraction** — a reusable recipe for scraping structured records from a website — and start its agent discovery. Discovery explores the site, builds the scrape/extract plan, and validates it against your schema. Poll [GET /extractions/{id}](#tag/extractions/get/extractions/{id}) until `status` is `ready`, then execute it with [POST /extractions/{id}/runs](#tag/extractions/post/extractions/{id}/runs). The extraction (`ext_...`) and its runs (`run_...`) are different resources. Creating an extraction charges discovery credits (returned as `credits_charged`). To see the price first, send `estimate_cost: true`. **Example — Create an extraction:** { "starting_url": "https://example.com/products", "goal_description": "Extract every product with its name and price", "output_record_json_schema": { "type": "object", "properties": { "name": { "type": "string" }, "price": { "type": "string" } } }, "required_keys": [ "name" ] } **Workflow:** Discovery is async but returns no run — poll `get_extraction` until `status` is 'ready', then execute with `run_extraction`.

Parametersnamemax_creditsstarting_urlrequiredestimate_costrequired_keysgoal_descriptionrequiredoutput_record_json_schemarequired

get_extraction

Get extraction

get extraction The extraction's status and definition. `status` is `discovering` while the agent builds the plan, then `ready` (or `discovery_failed`). Once `ready`, execute with [POST /extractions/{id}/runs](#tag/extractions/post/extractions/{id}/runs).

Parametersidrequired

list_monitors

List monitors

list monitors List the account's monitors, newest first. An item whose monitor runs a legacy enrichment carries `legacy: true`.

Takes no parameters.

create_monitor

Create monitor

create monitor Create a **monitor**: a schedule that fills a dataset's output columns again daily, weekly, or monthly, compares each cell with the previous run, and can POST results (or only changes) to a webhook. Pass `dataset_id` and optionally `columns` (output column names; every one when omitted); the rows are the dataset's, no `input`. Creation is free; every run charges the fill price. `estimate_cost: true` prices one run. `help` → `monitors`. **Example — Daily monitor on a dataset, webhook only on changes:** { "dataset_id": "ds_018f5b60-1234-7abc-89ab-0123456789ab", "columns": [ "Headcount", "Latest funding round" ], "cadence": "daily", "hour": 9, "minute": 0, "timezone": "UTC", "alert_rule": "on_diff", "output_format": "include_diffs", "webhook_url": "https://your-server.com/webhook" } **Example — Weekly monitor, every output column, results every run:** { "dataset_id": "ds_018f5b60-1234-7abc-89ab-0123456789ab", "cadence": "weekly", "day_of_week": 1, "hour": 7, "minute": 30, "timezone": "America/New_York", "webhook_url": "https://your-server.com/webhook" } **Workflow:** Creates a scheduled monitor. Check it with `get_monitor`, pause it with `update_monitor` (enabled: false), and list its runs with `list_monitor_runs`.

Parametershourrequiredinputminuterequiredcadencerequiredcolumnstimezonerequiredalert_ruledataset_idday_of_weekmax_creditswebhook_urlday_of_month+4 more

get_monitor

Get monitor

get monitor The monitor's schedule, webhook, next run time, and the dataset and `columns` it fills. A monitor on a legacy enrichment answers with `legacy`.

Parametersidrequired

update_monitor

Update monitor

update monitor Pause, resume, or repoint a monitor. `enabled: false` pauses, `enabled: true` resumes; `webhook_url` replaces the delivery URL; `columns` changes the output columns each run fills — `null` for every column (refused on a monitor on a legacy enrichment, whose response carries `legacy`). **Example — Pause:** { "enabled": false } **Example — Resume:** { "enabled": true } **Example — Fill two columns only:** { "columns": [ "Headcount", "Latest funding round" ] }

Parametersidrequiredcolumnsenabledwebhook_url

list_monitor_runs

List monitor runs

list monitor runs The monitor's run history, newest first. Fetch a specific run's data with [GET /runs/{id}/result](#tag/runs/get/runs/{id}/result). Supports `status`, `page`, and `per_page`. A monitor on a legacy enrichment answers with `legacy`.

Parametersidrequiredpagestatusper_page

search_agent

Search agent

search agent Ask a question and get an answer. This is meant for quick, relatively scoped one-off questions, like "What is the NAICS code for this company...". For more complex questions, use the `enrich/` endpoint. This uses the same AI + web-tool loop that fills a single agent-mode cell in an enrichment (web search, web scraping, PDF reading, HTTP requests), with no enrichment setup. The run is processed in the background while this request **long-polls up to `wait` seconds (default 50)** — most runs finish in time and return the answer inline in `output.result`. If the agent is still working when the budget elapses, the response comes back with `status: processing` and `output: null`; poll [GET /runs/{id}/result](#tag/runs/get/runs/{id}/result) (it long-polls too) until the run is terminal. Pass `output_schema` (a JSON Schema object) to get `output.result` back as a structured object matching your schema instead of free text. Unanswerable questions return the string `"not found"`. ## Quick example ```bash curl -X POST https://api.riveterhq.com/v1/search_agent \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"prompt": "Who is the current CEO of Anthropic, and when did they take the role?"}' ``` ## Credit costs - **1 credit** per call (same as one agent-mode enrichment cell), charged when the agent completes. Failed runs are not charged. **Example — A free-text question:** { "prompt": "Who is the current CEO of Anthropic, and when did they take the role?" } **Example — A structured answer via output_schema:** { "prompt": "Find the founding year and headquarters city of Anthropic", "output_schema": { "type": "object", "properties": { "founding_year": { "type": "integer" }, "headquarters_city": { "type": "string" } } } }

Parameterswaitpromptrequiredrun_keymax_creditsestimate_costoutput_schema

scrape

Scrape

scrape Scrape a webpage and return the text content **synchronously** — the only endpoint here that doesn't return a run to poll. Unchanged from the legacy API (response uses the legacy `request_status` format). ## Quick example ```bash curl -X POST https://api.riveterhq.com/v1/scrape \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"url": "https://example.com"}' ``` ## Credit costs - **With proxy**: 0.30 credits - **Without proxy**: 0.10 credits - **From cache**: 0.01 credits ## Proxy usage Scraping is not guaranteed to succeed without a proxy. Some websites may block requests or require specific geographic locations. To use a proxy, include `proxy_country_code` with a two-character country code (e.g. 'us', 'gb', 'de'). ## Caching Recently scraped pages are cached to save credits (0.01 credits on a cache hit). Set `skip_cache: true` to always fetch fresh content.

Parametersurlrequiredskip_cachemax_creditsestimate_costproxy_country_code

list_tools

List agent tools

list agent tools The tools an enrichment may list in `only_tools` / `additional_tools` or pin to an output column (`tool`): name, what it does, what a call takes (`inputs`, each with `required`; `input_groups` when any one complete set is enough) and gives back (`returns`) — the values a pinned column's row must carry or the agent must find —, credits per call (`price_note` when the price settles after the call — the LinkedIn email / phone tools only on a contact, `text_search_pdf` per page, `pdf` / `image` by tokens spent reading it), whether it is on by default, whether it needs opt-in and is enabled on this account, and for a tool that uses the account's own provider key (Apollo, Hunter, Findymail, curl, USPTO) whether one is linked (`api_key_linked`; refused until it is). Also the `budget` (credits per row) range and per-column default.

Takes no parameters.

get_account

Account

account Information about the account associated with the API key: plan, credit balance, and the key's metadata. Unchanged from the legacy API (response uses the legacy `request_status` format).

Takes no parameters.

help

Reference docs for using Riveter well. Call before writing an `output` column spec or when an error mentions a limit. Topics: overview, enrich_modes, column_config, run_when, formats, tools, examples, credits, datasets_vs_enrichment, datasets, pinned_columns, output_schema, limits, webhooks, monitors, errors.

Parameterstopicrequired

Version history

3
  1. v0.3.6LatestOct 30, 2026
  2. v0.3.5Oct 29, 2026
  3. v0.3.0Sep 16, 2026

Score

100% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 daysRequired25 pts
  • Auth declaredRequired10 pts
  • Tools listed15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts