{"openapi":"3.2.0","info":{"title":"Riveter API","description":"## Overview\n\nThe Riveter API lets you **enrich** data, **build datasets**, **scrape** webpages, quickly **search** the web, and **extract** data from complicated websites programmatically.\n\n- **An enrichment** takes rows of input data and fills in new columns using AI, web searches, web scrapes, and other tools. For example, given a list of companies, an enrichment can pull their tech stack, analyze their pricing structure, determine what security tools they use, and much more.\n- **A dataset** is a collection of rows — companies, people, products, URLs, or anything else you want to work with. You can build one from a natural-language prompt or a structured spec, and Riveter will generate the rows for you.\n- **A scrape** lets you turn a URL into easily parseable text.\n- **A quick_search** lets you quickly web search a query, and pull structured results with urls, titles, and snippets — synchronously, in one request.\n- **A search_agent call** asks one question and gets one AI-researched answer back — the same agent loop that fills a single enrichment cell, without setting up an enrichment.\n\nEvery asynchronous operation returns a **run** with an id like `run_...`, and every run — enrichment, dataset build, extraction, or search — is tracked, fetched, and stopped the same way through `/runs`.\n\n## The run lifecycle\n\nEvery kickoff endpoint (`/enrich`, `/datasets`, `/extractions/{id}/runs`, ...) returns `201 Created` with a **run**. From there:\n\n| Request | What it does |\n|---------|--------------|\n| `GET /runs/{id}` | Check status (`pending` → `enqueued` → `processing` → `success` or `stopped`) |\n| `GET /runs/{id}/result?wait=30` | Fetch the output. `wait` long-polls up to 50 seconds; `output` is `null` until the run finishes |\n| `POST /runs/{id}/stop` | Stop a run early |\n\nPrefer webhooks over polling: pass `webhook_url` on kickoff and Riveter POSTs the results to you when the run finishes. If you poll, an interval of 10-20 seconds is plenty.\n\nEvery kickoff and every `/runs` endpoint returns the same **run** — see the [Runs](#tag/runs) section for the full shape.\n\n## Legacy endpoints\n\nThis is the second generation of the Riveter API. The first generation used verb-style paths (`/run_new_enrichment`, `/run_status`, `/run_data`, `/build_dataset`, ...). Those endpoints are legacy: they keep working at the same paths, but new work should use this API. Every endpoint documented here is current — none are legacy.\n\nCommon legacy → current mappings: `/run_new_enrichment` → `/enrich`, `/run_enrichment` → `/enrich` + `enrichment_id`, `/run_status` → `/runs/{id}`, `/run_data` → `/runs/{id}/result`, `/build_dataset` → `/datasets`, `/monitor_enrichment` → `/monitors`. The full table is in the [legacy API docs](./openapi.legacy.yaml) (\"Migrating to the current API\").\n\n## Webhooks\n\nPass `webhook_url` in the JSON body when starting a run and Riveter POSTs the full results to your URL when it finishes (events: `run.completed`, `run.stopped`, `run.finished`). Dataset builds take `dataset_webhook_url`. Failed deliveries are retried up to 2 times; your endpoint should return a 2xx.\n\nThe webhook payload shape is shared with the legacy API — see the [legacy API docs](./openapi.legacy.yaml) (\"Webhooks\" section) for the full payload reference.\n\n## Authentication\n\nAll endpoints require an API key via the Authorization header:\n```\nAuthorization: Bearer YOUR_API_KEY\n```\n[Get an API key here](https://app.riveterhq.com/settings/api)\n\n## Rate limiting\n\nDefault: 30 requests per minute per endpoint group. Responses include `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` headers. Row caps: up to 10,000 rows per `/enrich` request with `enrichment_id`, 1,000 rows with an inline config (`output` or `prompt` + `attributes`).\n\n## MCP server\n\nUse Riveter from Claude, ChatGPT, Cursor, or any MCP-compatible AI assistant. Pick one of the two ways to connect.\n\n### Hosted server (claude.ai, Claude Desktop, Cowork, mobile, ChatGPT, Claude Code, Cursor)\n\nAdd `https://mcp.riveterhq.com/mcp` as a custom connector, then click Connect. A browser window opens on Riveter: sign in and click **Allow**. That creates an API key for the connection in [Settings → API keys](https://app.riveterhq.com/settings/api); revoke it there to disconnect. Nothing runs on your machine.\n\n**Claude Code:**\n```bash\nclaude mcp add --transport http riveter https://mcp.riveterhq.com/mcp\n```\nThen run `/mcp` inside Claude Code and choose Authenticate.\n\n**Cursor** — paste into your MCP config, then click Connect in the MCP settings:\n```json\n{\n  \"mcpServers\": {\n    \"riveter\": {\n      \"url\": \"https://mcp.riveterhq.com/mcp\"\n    }\n  }\n}\n```\n\nIf your client cannot open a browser, pass an [API key](https://app.riveterhq.com/settings/api) directly as a request header: `Authorization: Bearer YOUR_API_KEY` (Claude Code: `--header \"Authorization: Bearer YOUR_API_KEY\"`; Cursor: `\"headers\": { \"Authorization\": \"Bearer YOUR_API_KEY\" }`).\n\n### Local server (npx)\n\nRuns on your machine and needs Node.js and an [API key](https://app.riveterhq.com/settings/api). Use it when your client cannot reach remote servers.\n\n**Claude Code:**\n```bash\nclaude mcp add riveter \\\n  --env RIVETER_API_KEY=YOUR_API_KEY \\\n  -- npx -y --prefer-online riveter-mcp-server@latest\n```\n\n**Codex:**\n```bash\ncodex mcp add riveter \\\n  --env RIVETER_API_KEY=YOUR_API_KEY \\\n  -- npx -y --prefer-online riveter-mcp-server@latest\n```\n\n**Cursor / Windsurf / Claude Desktop** — paste into your MCP config:\n```json\n{\n  \"mcpServers\": {\n    \"riveter\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"--prefer-online\", \"riveter-mcp-server@latest\"],\n      \"env\": {\n        \"RIVETER_API_KEY\": \"YOUR_API_KEY\"\n      }\n    }\n  }\n}\n```\n\nBoth servers expose every API endpoint as a tool, with full descriptions and typed parameters. No setup beyond the API key.\n\n_**Updating:** Simply restart your AI client to load the new version — no need to remove and re-add the server. Riveter's MCP server always pulls the latest API version._\n\n## Official SDKs\n\nPrefer a typed client over raw HTTP — the SDKs handle auth, retries (429s and transient GET failures), the `wait` long-poll, polling until a run finishes (`wait_for_result`), and pagination:\n\n| Language | Install | Package |\n|----------|---------|---------|\n| TypeScript / JavaScript | `npm install riveter-sdk` | [riveter-sdk on npm](https://www.npmjs.com/package/riveter-sdk) |\n| Python | `pip install riveter-sdk` | [riveter-sdk on PyPI](https://pypi.org/project/riveter-sdk/) (import `riveter`) |\n| Ruby | `gem install riveter-sdk` | [riveter-sdk on RubyGems](https://rubygems.org/gems/riveter-sdk) (`require \"riveter\"`) |\n| Go | `go get github.com/riveterhq/riveter-go` | [riveterhq/riveter-go](https://github.com/riveterhq/riveter-go) |\n\nEvery endpoint on this page shows the equivalent SDK call in all four languages next to the request example.\n\n## Timestamps\n\nAll timestamps in responses are ISO 8601 strings with second precision and an explicit UTC offset (e.g. `2026-01-15T12:00:00Z`).\n\n## Errors\n\nErrors use real HTTP status codes and a uniform body:\n\n```json\n{ \"error\": { \"type\": \"not_found\", \"message\": \"No run found with id run_...\" } }\n```\n\nCommon `type` values: `bad_request`, `not_found`, `forbidden`, `duplicate_run_key`, `insufficient_credits`, `validation`, `not_implemented`.\n\nOne exception: authentication failures (`401`) come from the shared auth layer and use the legacy shape `{ \"request_status\": \"error\", \"message\": \"...\", \"error_type\": \"unauthorized\" }`.\n","version":"2.0.0","contact":{"name":"Riveter Support","url":"https://riveterhq.com","email":"support@riveterhq.com"}},"servers":[{"url":"https://api.riveterhq.com/v1","description":"Production server"}],"security":[{"ApiKeyAuth":[]}],"paths":{"/enrich":{"post":{"summary":"enrich","description":"Provide rows in `input`, tell Riveter what columns to add and a webhook to send data to, or get back a run to poll.\n\nThere are three ways to tell Riveter what to add. This is in order of preference:\n\n1. Run an existing enrichment (enrichment_id) — preferred.\n2. Run with a prompt + attributes — describe the columns in natural language.\n3. Run with a full output spec (output) — define each column exactly.\n\n## Input: inline columnar data\n\n`input` is a JSON object in columnar form:\n- Keys are column headers.\n- Values are arrays of strings. Every array must be the same length.\n- Each position across the arrays is one row.\n\nFor example, `{ \"Company\": [\"Apple\", \"Google\"], \"Website\": [\"apple.com\", \"google.com\"] }` is two rows:\n\n| Company | Website |\n|---------|-----------|\n| Apple   | apple.com |\n| Google  | google.com |\n\n## 1. run an existing enrichment (enrichment_id) (preferred)\n\nPass the id of a saved enrichment (`enr_...`). First build and fine-tune it in the [Riveter UI](https://app.riveterhq.com/enrichments), then run it with new rows. This is the preferred option: the configuration is fixed and tested, so results are the most consistent. Max 10,000 rows per request. Input column headers must match the enrichment's source-data columns.\n\n```bash\ncurl -X POST \"https://api.riveterhq.com/v1/enrich\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"enrichment_id\": \"enr_YOUR_ENRICHMENT_ID\",\n    \"input\": {\"Company Name\": [\"Acme Corp\", \"Tech Solutions Inc\"]}\n  }'\n```\n\n## 2. run from a prompt + attributes\n\nProvide a natural-language `prompt` and an `attributes` array of output column names. The AI generates the full column configuration for you. This needs no setup, but the configuration is generated fresh each time, so results can vary between runs. For consistent, repeatable results, save the enrichment once and run it by `enrichment_id` (option 1). Max 1,000 rows per request, max 10 attributes.\n\n```bash\ncurl -X POST \"https://api.riveterhq.com/v1/enrich\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"prompt\": \"Research each company\",\n    \"attributes\": [\"CEO\", \"Employee Count\", \"Industry\"],\n    \"input\": {\"Company\": [\"Apple\", \"Google\"]},\n    \"webhook_url\": \"https://your-server.com/webhook\"\n  }'\n```\n\n## 3. run from a full output spec\n\nDefine each output column exactly: the prompt, contexts, tools, and format per column. Use this when you need precise control over how each column runs. See the `EnrichmentOutputSpec` schema. Max 1,000 rows per request.\n\n```bash\ncurl -X POST \"https://api.riveterhq.com/v1/enrich\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"output\": {\n      \"Employee Count\": {\n        \"prompt\": \"Find the number of employees at this company\",\n        \"contexts\": [\"Company\"],\n        \"format\": \"number\"\n      }\n    },\n    \"input\": {\"Company\": [\"Apple\", \"Google\"]}\n  }'\n```\n\n## Use a built dataset as the input\n\nInstead of inline `input`, pass `dataset_id` to enrich the rows of a completed dataset build (`ds_...`). The row source is exactly one of `input` or `dataset_id`, and it combines with any of the three column-config options above.\n\n```bash\ncurl -X POST \"https://api.riveterhq.com/v1/enrich\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"enrichment_id\": \"enr_YOUR_ENRICHMENT_ID\",\n    \"dataset_id\": \"ds_YOUR_DATASET_ID\"\n  }'\n```\n\n## After the kickoff\n\nThe response is a [run](#model/run). Poll [GET /runs/{id}](#tag/runs/get/runs/{id}), fetch results with [GET /runs/{id}/result](#tag/runs/get/runs/{id}/result), or just wait for your `webhook_url` to be called.\n","operationId":"enrich","x-mcp-open-world":true,"x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\nconst run = await riveter.enrich({\n  enrichment_id: \"enr_YOUR_ENRICHMENT_ID\",\n  input: { \"Company Name\": [\"Acme Corp\", \"Tech Solutions Inc\"] },\n});\nconst result = await riveter.runs.waitForResult(run.id);\nconsole.log(result.output);\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\nrun = riveter.enrich(\n    enrichment_id=\"enr_YOUR_ENRICHMENT_ID\",\n    input={\"Company Name\": [\"Acme Corp\", \"Tech Solutions Inc\"]},\n)\nresult = riveter.runs.wait_for_result(run.id)\nprint(result.output)\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\nrun = riveter.enrich(\n  enrichment_id: \"enr_YOUR_ENRICHMENT_ID\",\n  input: { \"Company Name\" => [\"Acme Corp\", \"Tech Solutions Inc\"] }\n)\nresult = riveter.runs.wait_for_result(run.id)\nputs result.output\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\nctx := context.Background()\nrun, err := client.Enrich(ctx, riveter.EnrichParams{\n    EnrichmentID: \"enr_YOUR_ENRICHMENT_ID\",\n    Input:        map[string][]string{\"Company Name\": {\"Acme Corp\", \"Tech Solutions Inc\"}},\n})\nresult, err := client.Runs.WaitForResult(ctx, run.ID, nil)\nfmt.Println(string(result.Output))\n"}],"tags":["Enrich"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enrichment_id":{"type":"string","description":"Config source: id of a saved enrichment (enr_...)"},"output":{"$ref":"#/components/schemas/EnrichmentOutputSpec","description":"Config source: full column spec"},"prompt":{"type":"string","description":"Config source: natural-language instructions (requires attributes)"},"attributes":{"type":"array","items":{"type":"string"},"maxItems":10,"description":"Config source: output column names to auto-generate (requires prompt)"},"input":{"$ref":"#/components/schemas/EnrichmentInputData","description":"Row source: inline columnar data"},"dataset_id":{"type":"string","description":"Row source: id of a completed dataset build (ds_...)"},"run_key":{"type":"string","maxLength":255,"pattern":"^[A-Za-z0-9._~-]+$","description":"Optional idempotency key, unique per account. Becomes the run id (\"run_<run_key>\"),\nso it is limited to letters, digits, and . _ ~ - characters. A duplicate returns 409.\n"},"webhook_url":{"type":"string","format":"uri","description":"URL to POST the results to when the run completes"},"allow_duplicate_input":{"type":"boolean","default":false,"description":"With enrichment_id — allow re-running rows already present in the enrichment"}}},"examples":{"saved_enrichment":{"summary":"Run a saved enrichment","value":{"enrichment_id":"enr_018f5b60-1234-7abc-89ab-0123456789ab","input":{"Company Name":["Acme Corp","Tech Solutions Inc"]}}},"prompt_and_attributes":{"summary":"Prompt + attributes (auto-generated config)","value":{"prompt":"Research each company","attributes":["CEO","Employee Count","Industry"],"input":{"Company":["Apple","Google"]},"webhook_url":"https://your-server.com/webhook"}},"full_output_spec":{"summary":"Full output specification","value":{"output":{"Employee Count":{"prompt":"Find the number of employees at this company","contexts":["Company"],"format":"number"}},"input":{"Company":["Apple","Google"]}}},"enrich_dataset_rows":{"summary":"Enrich the rows of a completed dataset build","value":{"enrichment_id":"enr_018f5b60-1234-7abc-89ab-0123456789ab","dataset_id":"ds_018f6a70-1234-7abc-89ab-0123456789ab"}}}}}},"responses":{"201":{"description":"Run started — poll /runs/{id} or wait for the webhook","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Run"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/UnprocessableEntity"}}}},"/runs/{id}":{"get":{"summary":"run status","description":"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.\n","operationId":"getRun","x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\nconst run = await riveter.runs.get(\"run_YOUR_RUN_ID\");\nconsole.log(run.status, run.progress);\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\nrun = riveter.runs.get(\"run_YOUR_RUN_ID\")\nprint(run.status, run.progress)\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\nrun = riveter.runs.get(\"run_YOUR_RUN_ID\")\nputs run.status\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\nrun, err := client.Runs.Get(context.Background(), \"run_YOUR_RUN_ID\")\nfmt.Println(run.Status)\n"}],"tags":["Runs"],"parameters":[{"name":"id","in":"path","required":true,"description":"The run id (run_...)","schema":{"type":"string"}}],"responses":{"200":{"description":"The run","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Run"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/runs/{id}/result":{"get":{"summary":"run result","description":"The run plus `output`. `output` is `null` until the run reaches a terminal state..\n\nPass `?wait=N` (max 50) to long-poll: the request holds until the run finishes or the budget elapses, whichever comes first.\n\n## Output shape by run type\n- **enrichment** — an object mapping column headers to arrays of cell objects: `{ \"Company\": [{\"value\": \"Apple\"}], \"CEO\": [{\"value\": \"Tim Cook\"}] }`\n- **dataset_build** — an object mapping column headers to arrays of cell objects (same columnar shape as enrichment)\n- **extraction** — the extracted records as an array of JSON objects (matching your `output_record_json_schema`)\n- **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.)\n- **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.\n","operationId":"getRunResult","x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\n// One 30s long-poll:\nconst result = await riveter.runs.result(\"run_YOUR_RUN_ID\", { wait: 30 });\n// Or keep polling until the run finishes (default budget 10 min):\nconst finished = await riveter.runs.waitForResult(\"run_YOUR_RUN_ID\");\nconsole.log(finished.output);\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\n# One 30s long-poll:\nresult = riveter.runs.result(\"run_YOUR_RUN_ID\", wait=30)\n# Or keep polling until the run finishes (default budget 10 min):\nfinished = riveter.runs.wait_for_result(\"run_YOUR_RUN_ID\")\nprint(finished.output)\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\n# One 30s long-poll:\nresult = riveter.runs.result(\"run_YOUR_RUN_ID\", wait: 30)\n# Or keep polling until the run finishes (default budget 10 min):\nfinished = riveter.runs.wait_for_result(\"run_YOUR_RUN_ID\")\nputs finished.output\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\nctx := context.Background()\n// One 30s long-poll:\nresult, err := client.Runs.Result(ctx, \"run_YOUR_RUN_ID\", &riveter.ResultOptions{Wait: 30})\n// Or keep polling until the run finishes (default budget 10 min):\nfinished, err := client.Runs.WaitForResult(ctx, \"run_YOUR_RUN_ID\", nil)\nfmt.Println(string(finished.Output))\n"}],"tags":["Runs"],"parameters":[{"name":"id","in":"path","required":true,"description":"The run id (run_...)","schema":{"type":"string"}},{"name":"wait","in":"query","required":false,"description":"Long-poll budget in seconds (0–50, default 0)","schema":{"type":"integer","minimum":0,"maximum":50,"default":0}}],"responses":{"200":{"description":"The run with output (null while still running)","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Run"},{"type":"object","properties":{"output":{"description":"The run's results (null until ready) — shape depends on run type, see the endpoint description","type":["object","array","null"]}}}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/UnprocessableEntity"}}}},"/runs/{id}/stop":{"post":{"summary":"stop run","description":"Stop a run early. Works for every run type. Already-finished runs are left untouched; the response is the run either way.\n","operationId":"stopRun","x-mcp-destructive":true,"x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\nconst run = await riveter.runs.stop(\"run_YOUR_RUN_ID\");\nconsole.log(run.status); // \"stopped\"\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\nrun = riveter.runs.stop(\"run_YOUR_RUN_ID\")\nprint(run.status)  # \"stopped\"\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\nrun = riveter.runs.stop(\"run_YOUR_RUN_ID\")\nputs run.status # \"stopped\"\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\nrun, err := client.Runs.Stop(context.Background(), \"run_YOUR_RUN_ID\")\nfmt.Println(run.Status) // \"stopped\"\n"}],"tags":["Runs"],"parameters":[{"name":"id","in":"path","required":true,"description":"The run id (run_...)","schema":{"type":"string"}}],"responses":{"200":{"description":"The run after the stop","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Run"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/UnprocessableEntity"}}}},"/runs":{"get":{"summary":"list runs","description":"List the account's runs, newest first. Every async operation shows up here — enrichment runs, dataset builds, extractions, and quick searches.\n\nFilter by `type` (comma-separated), `status`, `enrichment_id`, `monitor_id`, and `created_after` / `created_before` (ISO 8601). Paginate with `page` / `per_page`.\n","operationId":"listRuns","x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\nconst page = await riveter.runs.list({ status: \"success\" });\nfor await (const run of page) { // auto-pages through every result\n  console.log(run.id, run.type);\n}\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\npage = riveter.runs.list(status=\"success\")\nfor run in page.auto_paging_iter():  # pages through every result\n    print(run.id, run.type)\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\npage = riveter.runs.list(status: \"success\")\npage.auto_paging_each do |run| # pages through every result\n  puts \"#{run.id} #{run.type}\"\nend\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\nctx := context.Background()\npage, err := client.Runs.List(ctx, &riveter.ListRunsParams{Status: \"success\"})\nfor {\n    for _, run := range page.Runs {\n        fmt.Println(run.ID, run.Type)\n    }\n    if !page.HasNextPage() {\n        break\n    }\n    page, err = page.NextPage(ctx)\n}\n"}],"tags":["Runs"],"parameters":[{"name":"type","in":"query","required":false,"description":"Comma-separated run types: enrichment, dataset_build, extraction, scrape, quick_search, search_agent","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"Filter by run status","schema":{"type":"string","enum":["pending","enqueued","processing","success","stopped"]}},{"name":"enrichment_id","in":"query","required":false,"description":"Only runs of this enrichment (enr_...)","schema":{"type":"string"}},{"name":"monitor_id","in":"query","required":false,"description":"Only runs of this monitor (mon_...)","schema":{"type":"string"}},{"name":"created_after","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"created_before","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":1}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","default":25,"maximum":100}}],"responses":{"200":{"description":"Runs listed","content":{"application/json":{"schema":{"type":"object","properties":{"runs":{"type":"array","items":{"$ref":"#/components/schemas/RunListItem"}},"pagination":{"$ref":"#/components/schemas/Pagination"}},"required":["runs","pagination"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/runs/summary":{"get":{"summary":"list runs (summary)","description":"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=...`.\n","operationId":"runsSummary","x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\nconst summary = await riveter.runs.summary();\nconsole.log(summary.counts);\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\nsummary = riveter.runs.summary()\nprint(summary.counts)\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\nsummary = riveter.runs.summary\nputs summary.counts\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\nsummary, err := client.Runs.Summary(context.Background())\nfmt.Printf(\"%+v\\n\", summary.Counts)\n"}],"tags":["Runs"],"responses":{"200":{"description":"Run counts by status","content":{"application/json":{"schema":{"type":"object","properties":{"counts":{"type":"object","properties":{"pending":{"type":"integer"},"enqueued":{"type":"integer"},"processing":{"type":"integer"},"success":{"type":"integer"},"stopped":{"type":"integer"}}}}},"example":{"counts":{"pending":0,"enqueued":1,"processing":2,"success":40,"stopped":3}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/enrichments":{"get":{"summary":"list enrichments","description":"List the account's enrichments with their output column configuration.","operationId":"listEnrichments","x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\nconst enrichments = await riveter.enrichments.list();\nfor (const enrichment of enrichments) {\n  console.log(enrichment.id, enrichment.name);\n}\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\nfor enrichment in riveter.enrichments.list():\n    print(enrichment.id, enrichment.name)\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\nriveter.enrichments.list.each do |enrichment|\n  puts \"#{enrichment.id} #{enrichment.name}\"\nend\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\nenrichments, err := client.Enrichments.List(context.Background())\nfor _, enrichment := range enrichments {\n    fmt.Println(enrichment.ID, enrichment.Name)\n}\n"}],"tags":["Enrich"],"responses":{"200":{"description":"Enrichments listed","content":{"application/json":{"schema":{"type":"object","properties":{"enrichments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Enrichment id (enr_...)"},"name":{"type":"string"},"status":{"type":"string"},"app_url":{"type":"string","format":"uri"},"columns":{"type":"object","description":"Output column configuration keyed by column header"}}}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/UnprocessableEntity"}}},"post":{"summary":"create enrichment","description":"Create an enrichment (no run) from a **completed dataset build**: the dataset's rows become the enrichment's input rows, and its attributes become output columns. Configure further in the UI or via [PATCH /enrichments/{id}](#tag/enrich/patch/enrichments/{id}), then run with [POST /enrich](#tag/enrich/post/enrich).\n","operationId":"createEnrichment","x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\nconst created = await riveter.enrichments.create({\n  dataset_id: \"ds_YOUR_DATASET_ID\",\n});\nconsole.log(created.id); // enr_...\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\ncreated = riveter.enrichments.create(dataset_id=\"ds_YOUR_DATASET_ID\")\nprint(created.id)  # enr_...\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\ncreated = riveter.enrichments.create(dataset_id: \"ds_YOUR_DATASET_ID\")\nputs created.id # enr_...\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\ncreated, err := client.Enrichments.Create(context.Background(), \"ds_YOUR_DATASET_ID\")\nfmt.Println(created.ID) // enr_...\n"}],"tags":["Enrich"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"dataset_id":{"type":"string","description":"Id of a completed dataset build (ds_...)"}},"required":["dataset_id"]}}}},"responses":{"201":{"description":"Enrichment created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The new enrichment's id (enr_...)"},"name":{"type":"string"},"app_url":{"type":"string","format":"uri"},"dataset_id":{"type":"string"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/enrichments/{id}":{"get":{"summary":"read enrichment","description":"The enrichment's structure: its input (source-data) columns and full output column configuration — the same shape you would send to [POST /enrich](#tag/enrich/post/enrich) as `output`.\n","operationId":"getEnrichment","x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\nconst enrichment = await riveter.enrichments.get(\"enr_YOUR_ENRICHMENT_ID\");\nconsole.log(enrichment.input, enrichment.output);\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\nenrichment = riveter.enrichments.get(\"enr_YOUR_ENRICHMENT_ID\")\nprint(enrichment.input, enrichment.output)\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\nenrichment = riveter.enrichments.get(\"enr_YOUR_ENRICHMENT_ID\")\nputs enrichment.input.inspect\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\nenrichment, err := client.Enrichments.Get(context.Background(), \"enr_YOUR_ENRICHMENT_ID\")\nfmt.Println(enrichment.Input)\n"}],"tags":["Enrich"],"parameters":[{"name":"id","in":"path","required":true,"description":"The enrichment id (enr_...)","schema":{"type":"string"}}],"responses":{"200":{"description":"Enrichment structure","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"},"app_url":{"type":"string","format":"uri"},"input":{"type":"object","description":"Source-data (input) columns"},"output":{"$ref":"#/components/schemas/EnrichmentOutputSpec"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"summary":"update enrichment","description":"Add, update, rename, or delete output columns, or reorder columns. Send the column changes keyed by column header inside `output` (recommended); a `column_order` array reorders columns.\n\nExisting columns can be partially updated; new column names must include a full configuration; set `\"delete\": true` on a column to remove it. Columns use the same fields as the `output` spec on [POST /enrich](#tag/enrich/post/enrich).\n","operationId":"updateEnrichment","x-mcp-destructive":true,"x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\nconst changes = await riveter.enrichments.update(\"enr_YOUR_ENRICHMENT_ID\", {\n  output: {\n    CEO: { prompt: \"Find the CEO's full name\", contexts: [\"Company\"] },\n  },\n});\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\nchanges = riveter.enrichments.update(\n    \"enr_YOUR_ENRICHMENT_ID\",\n    output={\"CEO\": {\"prompt\": \"Find the CEO's full name\", \"contexts\": [\"Company\"]}},\n)\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\nchanges = riveter.enrichments.update(\n  \"enr_YOUR_ENRICHMENT_ID\",\n  output: { \"CEO\" => { prompt: \"Find the CEO's full name\", contexts: [\"Company\"] } }\n)\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\nchanges, err := client.Enrichments.Update(context.Background(), \"enr_YOUR_ENRICHMENT_ID\",\n    riveter.UpdateEnrichmentParams{\n        Output: map[string]riveter.OutputColumnConfig{\n            \"CEO\": {Prompt: \"Find the CEO's full name\", Contexts: []string{\"Company\"}},\n        },\n    })\n"}],"tags":["Enrich"],"parameters":[{"name":"id","in":"path","required":true,"description":"The enrichment id (enr_...)","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"output":{"$ref":"#/components/schemas/EnrichmentOutputSpec","description":"Column changes keyed by column header"},"column_order":{"type":"array","items":{"type":"string"},"description":"Optional full column ordering (column headers)"}}},"examples":{"add_a_column":{"summary":"Add a column","value":{"output":{"CEO":{"prompt":"Find the company's CEO","contexts":["Company Name"],"format":"text"}}}},"delete_a_column":{"summary":"Delete a column","value":{"output":{"Old Column":{"delete":true}}}}}}}},"responses":{"200":{"description":"Enrichment updated — response lists the applied changes","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/UnprocessableEntity"}}}},"/enrichments/{id}/datasets":{"post":{"summary":"enrichment → dataset","description":"Build a dataset **shaped for this enrichment**: identifiers are derived from the enrichment's source-data columns automatically, so generated rows land as valid input rows.\n\nOptionally set `auto_run_enrichment: true` to run the enrichment on the rows as soon as the build completes (the kickoff response then carries `enrichment_run_id`).\n\nReturns the dataset-build run — poll it via [GET /runs/{id}](#tag/runs/get/runs/{id}).\n","operationId":"buildDatasetForEnrichment","x-mcp-open-world":true,"x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\nconst run = await riveter.enrichments.buildDataset(\"enr_YOUR_ENRICHMENT_ID\", {\n  prompt: \"US fintech startups\",\n  max_items: 100,\n  auto_run_enrichment: true,\n});\nconst result = await riveter.runs.waitForResult(run.id);\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\nrun = riveter.enrichments.build_dataset(\n    \"enr_YOUR_ENRICHMENT_ID\",\n    prompt=\"US fintech startups\",\n    max_items=100,\n    auto_run_enrichment=True,\n)\nresult = riveter.runs.wait_for_result(run.id)\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\nrun = riveter.enrichments.build_dataset(\n  \"enr_YOUR_ENRICHMENT_ID\",\n  prompt: \"US fintech startups\",\n  max_items: 100,\n  auto_run_enrichment: true\n)\nresult = riveter.runs.wait_for_result(run.id)\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\nctx := context.Background()\nrun, err := client.Enrichments.BuildDataset(ctx, \"enr_YOUR_ENRICHMENT_ID\",\n    riveter.BuildDatasetForEnrichmentParams{\n        Prompt:            \"US fintech startups\",\n        MaxItems:          100,\n        AutoRunEnrichment: true,\n    })\nresult, err := client.Runs.WaitForResult(ctx, run.ID, nil)\n"}],"tags":["Enrich"],"parameters":[{"name":"id","in":"path","required":true,"description":"The enrichment id (enr_...)","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"prompt":{"type":"string","description":"What rows to generate (e.g. \"US-based fintech startups\")"},"qualifiers":{"type":"array","items":{"type":"string"},"description":"Optional constraints each row must satisfy (e.g. \"B2B\", \"founded after 2015\")"},"max_items":{"type":"integer","description":"Max rows to generate (capped by your plan)"},"dataset_webhook_url":{"type":"string","format":"uri","description":"URL to POST the dataset results to when the build completes"},"auto_run_enrichment":{"type":"boolean","default":false,"description":"Run the enrichment automatically when the build completes"},"auto_run_enrichment_webhook_url":{"type":"string","format":"uri","description":"Webhook for the auto-run enrichment results"}},"required":["prompt"]},"examples":{"build_and_auto_run":{"summary":"Build rows and auto-run the enrichment","value":{"prompt":"US-based fintech startups","qualifiers":["B2B","founded after 2015"],"max_items":100,"auto_run_enrichment":true}}}}}},"responses":{"201":{"description":"Dataset build started — the run plus dataset_id / enrichment_id / max_items (and enrichment_run_id when auto-running)","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Run"},{"type":"object","properties":{"dataset_id":{"type":"string"},"enrichment_id":{"type":"string"},"max_items":{"type":"integer"},"enrichment_run_id":{"type":"string","description":"Present when auto_run_enrichment is true"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/UnprocessableEntity"}}}},"/datasets":{"post":{"summary":"build dataset","description":"Build a dataset from a natural-language prompt, a structured spec, or both. Riveter generates the rows for you.\n\n- **Prompt only** — e.g. \"top 50 US SaaS companies with their websites\". The builder analyzes the prompt into identifiers/qualifiers/attributes automatically.\n- **Structured spec** — `identifiers` (what each row is, e.g. \"Company name\"), `qualifiers` (constraints rows must satisfy), and `attributes` (extra columns to fill in).\n- **Both** — the prompt is combined with the spec.\n\nSet `auto_run_enrichment: true` to create an enrichment from the finished dataset and run it in one step — the easiest way to go from idea to enriched data.\n\nReturns the dataset-build run; poll [GET /runs/{id}](#tag/runs/get/runs/{id}) and fetch rows with [GET /runs/{id}/result](#tag/runs/get/runs/{id}/result), or pass `dataset_webhook_url`.\n","operationId":"buildDataset","x-mcp-open-world":true,"x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\nconst run = await riveter.datasets.build({\n  prompt: \"Top 100 US fintech startups\",\n  max_items: 100,\n});\nconst result = await riveter.runs.waitForResult(run.id);\nconsole.log(result.output);\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\nrun = riveter.datasets.build(\n    prompt=\"Top 100 US fintech startups\",\n    max_items=100,\n)\nresult = riveter.runs.wait_for_result(run.id)\nprint(result.output)\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\nrun = riveter.datasets.build(\n  prompt: \"Top 100 US fintech startups\",\n  max_items: 100\n)\nresult = riveter.runs.wait_for_result(run.id)\nputs result.output\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\nctx := context.Background()\nrun, err := client.Datasets.Build(ctx, riveter.BuildDatasetParams{\n    Prompt:   \"Top 100 US fintech startups\",\n    MaxItems: 100,\n})\nresult, err := client.Runs.WaitForResult(ctx, run.ID, nil)\nfmt.Println(string(result.Output))\n"}],"tags":["Datasets"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"prompt":{"type":"string","description":"Natural-language description of the dataset (required unless identifiers are given)"},"identifiers":{"type":"array","items":{"type":"string"},"description":"What each row is (e.g. [\"Company name\", \"Website\"])"},"qualifiers":{"type":"array","items":{"type":"string"},"description":"Constraints each row must satisfy"},"attributes":{"type":"array","items":{"type":"string"},"description":"Extra columns to fill in per row"},"max_items":{"type":"integer","description":"Max rows to generate (capped by your plan)"},"dataset_webhook_url":{"type":"string","format":"uri","description":"URL to POST the dataset results to when the build completes"},"auto_run_enrichment":{"type":"boolean","default":false,"description":"Create an enrichment from the finished dataset and run it automatically"},"auto_run_enrichment_webhook_url":{"type":"string","format":"uri","description":"Webhook for the auto-run enrichment results"}}},"examples":{"prompt_with_spec":{"summary":"Prompt with identifiers and qualifiers","value":{"prompt":"Top 50 US SaaS companies with their websites","identifiers":["Company name","Website"],"qualifiers":["US-based","SaaS"],"max_items":50}},"structured_spec":{"summary":"Structured spec","value":{"identifiers":["Company name","Website"],"qualifiers":["US-based","SaaS"],"attributes":["CEO","Employee count"],"max_items":50}},"build_and_enrich":{"summary":"Build and auto-enrich in one step","value":{"prompt":"Top 50 US SaaS companies","attributes":["CEO","Revenue"],"max_items":50,"auto_run_enrichment":true,"auto_run_enrichment_webhook_url":"https://your-server.com/webhook"}}}}}},"responses":{"201":{"description":"Dataset build started — the run plus dataset_id / max_items (and enrichment_run_id when auto-running)","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Run"},{"type":"object","properties":{"dataset_id":{"type":"string"},"max_items":{"type":"integer"},"enrichment_run_id":{"type":"string","description":"Present when auto_run_enrichment is true"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/UnprocessableEntity"}}}},"/datasets/{id}/extend":{"post":{"summary":"extend dataset","description":"Generate **new rows** for an existing completed dataset build. The new rows are deduplicated against the source build's rows. Identifiers and attributes are inherited from the source and cannot be overridden; `qualifiers` and `max_items` may be replaced, and an optional `prompt` adds a new instruction.\n\nReturns a fresh dataset-build run (the source build is untouched).\n","operationId":"extendDataset","x-mcp-open-world":true,"x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\nconst run = await riveter.datasets.extend(\"ds_YOUR_DATASET_ID\", {\n  max_items: 50,\n});\nconst result = await riveter.runs.waitForResult(run.id);\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\nrun = riveter.datasets.extend(\"ds_YOUR_DATASET_ID\", max_items=50)\nresult = riveter.runs.wait_for_result(run.id)\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\nrun = riveter.datasets.extend_dataset(\"ds_YOUR_DATASET_ID\", max_items: 50)\nresult = riveter.runs.wait_for_result(run.id)\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\nctx := context.Background()\nrun, err := client.Datasets.Extend(ctx, \"ds_YOUR_DATASET_ID\",\n    riveter.ExtendDatasetParams{MaxItems: 50})\nresult, err := client.Runs.WaitForResult(ctx, run.ID, nil)\n"}],"tags":["Datasets"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the source dataset build (ds_...)","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"prompt":{"type":"string","description":"Optional new instruction (e.g. \"more rows like these but in Europe\")"},"qualifiers":{"type":"array","items":{"type":"string"},"description":"Optional replacement qualifiers (defaults to the source's)"},"max_items":{"type":"integer","description":"Max new rows (defaults to the source's max_items)"},"dataset_webhook_url":{"type":"string","format":"uri"},"auto_run_enrichment":{"type":"boolean","default":false},"auto_run_enrichment_webhook_url":{"type":"string","format":"uri"}}}}}},"responses":{"201":{"description":"Extension build started — the run plus dataset_id / source_dataset_id / max_items","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Run"},{"type":"object","properties":{"dataset_id":{"type":"string","description":"The new build's dataset id"},"source_dataset_id":{"type":"string"},"max_items":{"type":"integer"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/UnprocessableEntity"}}}},"/configured_datasets/{id}/build":{"post":{"summary":"build configured dataset","description":"Run a **configured dataset** — a reusable, pre-configured dataset template (id `cds_...`) set up for your account. 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.\n\nReturns the dataset-build run; poll [GET /runs/{id}](#tag/runs/get/runs/{id}).\n","operationId":"buildConfiguredDataset","x-mcp-open-world":true,"x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\nconst run = await riveter.configuredDatasets.build(\"cds_YOUR_CONFIGURED_DATASET_ID\", {\n  parameters: { City: \"Denver\" },\n});\nconst result = await riveter.runs.waitForResult(run.id);\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\nrun = riveter.configured_datasets.build(\n    \"cds_YOUR_CONFIGURED_DATASET_ID\",\n    parameters={\"City\": \"Denver\"},\n)\nresult = riveter.runs.wait_for_result(run.id)\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\nrun = riveter.configured_datasets.build(\n  \"cds_YOUR_CONFIGURED_DATASET_ID\",\n  parameters: { \"City\" => \"Denver\" }\n)\nresult = riveter.runs.wait_for_result(run.id)\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\nctx := context.Background()\nrun, err := client.ConfiguredDatasets.Build(ctx, \"cds_YOUR_CONFIGURED_DATASET_ID\",\n    riveter.BuildConfiguredDatasetParams{Parameters: map[string]string{\"City\": \"Denver\"}})\nresult, err := client.Runs.WaitForResult(ctx, run.ID, nil)\n"}],"tags":["Datasets"],"parameters":[{"name":"id","in":"path","required":true,"description":"Configured dataset id (cds_...)","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"parameters":{"type":"object","description":"Values for the template's placeholders (keys defined by the template)"},"tier":{"type":"string","description":"Optional pricing/depth tier when the template defines tiers"},"dataset_webhook_url":{"type":"string","format":"uri","description":"URL to POST the dataset results to when the build completes"}}},"examples":{"with_parameters":{"summary":"Fill in template parameters","value":{"parameters":{"practice_type":"dentists","state":"ohio"}}}}}}},"responses":{"201":{"description":"Build started — the run plus dataset_id / configured_dataset_id / max_items / tier / credits_charged","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Run"},{"type":"object","properties":{"dataset_id":{"type":"string"},"configured_dataset_id":{"type":"string"},"max_items":{"type":"integer"},"tier":{"type":["string","null"]},"credits_charged":{"type":"number"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/UnprocessableEntity"}}}},"/extractions/{id}/runs":{"post":{"summary":"run extraction","description":"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`.\n\n`variables` fills any `{{ placeholder }}` values the plan defines (e.g. a search term or location). Each run charges run credits (`credits_charged`).\n","operationId":"runExtraction","x-mcp-open-world":true,"x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\nconst run = await riveter.extractions.run(\"ext_YOUR_EXTRACTION_ID\", {\n  variables: { location: \"Denver\" },\n});\nconst result = await riveter.runs.waitForResult(run.id);\nconsole.log(result.output);\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\nrun = riveter.extractions.run(\n    \"ext_YOUR_EXTRACTION_ID\",\n    variables={\"location\": \"Denver\"},\n)\nresult = riveter.runs.wait_for_result(run.id)\nprint(result.output)\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\nrun = riveter.extractions.run(\n  \"ext_YOUR_EXTRACTION_ID\",\n  variables: { \"location\" => \"Denver\" }\n)\nresult = riveter.runs.wait_for_result(run.id)\nputs result.output\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\nctx := context.Background()\nrun, err := client.Extractions.Run(ctx, \"ext_YOUR_EXTRACTION_ID\",\n    riveter.RunExtractionParams{Variables: map[string]string{\"location\": \"Denver\"}})\nresult, err := client.Runs.WaitForResult(ctx, run.ID, nil)\nfmt.Println(string(result.Output))\n"}],"tags":["Extractions"],"parameters":[{"name":"id","in":"path","required":true,"description":"The extraction id (ext_...)","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"variables":{"type":"object","description":"Values for the plan's placeholders"},"webhook_url":{"type":"string","format":"uri","description":"URL to POST the records to when the run completes"}}}}}},"responses":{"201":{"description":"Extraction run started — the run plus merged variables / credits_charged (and a validation_warning when the plan's last discovery validation did not pass)","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Run"},{"type":"object","properties":{"variables":{"type":"object"},"credits_charged":{"type":"number"},"validation_warning":{"type":"string","description":"Present when the last discovery validation did not pass"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/UnprocessableEntity"}}}},"/extractions":{"post":{"summary":"create extraction","description":"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.\n\nPoll [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.\n\nCreating an extraction charges discovery credits (returned as `credits_charged`).\n","operationId":"createExtraction","x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\nconst extraction = await riveter.extractions.create({\n  starting_url: \"https://example.com/directory\",\n  goal_description: \"Extract every listed company\",\n  output_record_json_schema: {\n    type: \"object\",\n    properties: { name: { type: \"string\" }, website: { type: \"string\" } },\n  },\n});\nconsole.log(extraction.id); // ext_...\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\nextraction = riveter.extractions.create(\n    starting_url=\"https://example.com/directory\",\n    goal_description=\"Extract every listed company\",\n    output_record_json_schema={\n        \"type\": \"object\",\n        \"properties\": {\"name\": {\"type\": \"string\"}, \"website\": {\"type\": \"string\"}},\n    },\n)\nprint(extraction.id)  # ext_...\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\nextraction = riveter.extractions.create(\n  starting_url: \"https://example.com/directory\",\n  goal_description: \"Extract every listed company\",\n  output_record_json_schema: {\n    \"type\" => \"object\",\n    \"properties\" => { \"name\" => { \"type\" => \"string\" }, \"website\" => { \"type\" => \"string\" } }\n  }\n)\nputs extraction.id # ext_...\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\nextraction, err := client.Extractions.Create(context.Background(),\n    riveter.CreateExtractionParams{\n        StartingURL:     \"https://example.com/directory\",\n        GoalDescription: \"Extract every listed company\",\n        OutputRecordJSONSchema: map[string]any{\n            \"type\": \"object\",\n            \"properties\": map[string]any{\n                \"name\":    map[string]any{\"type\": \"string\"},\n                \"website\": map[string]any{\"type\": \"string\"},\n            },\n        },\n    })\nfmt.Println(extraction.ID) // ext_...\n"}],"tags":["Extractions"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"starting_url":{"type":"string","format":"uri","description":"Where the agent starts exploring"},"goal_description":{"type":"string","description":"What records to extract, in plain language"},"output_record_json_schema":{"type":"object","description":"JSON schema of one output record"},"name":{"type":"string","description":"Optional display name"},"required_keys":{"type":"array","items":{"type":"string"},"description":"Record keys that must be non-empty for a record to count"}},"required":["starting_url","goal_description","output_record_json_schema"]},"examples":{"create":{"summary":"Create an extraction","value":{"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"]}}}}}},"responses":{"201":{"description":"Extraction created, discovery started","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Extraction id (ext_...)"},"name":{"type":"string"},"status":{"type":"string","enum":["discovering"]},"app_url":{"type":"string","format":"uri"},"credits_charged":{"type":"number"},"required_keys":{"type":"array","items":{"type":"string"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/UnprocessableEntity"}}}},"/extractions/{id}":{"get":{"summary":"get extraction","description":"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).\n","operationId":"getExtraction","x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\nconst extraction = await riveter.extractions.get(\"ext_YOUR_EXTRACTION_ID\");\nconsole.log(extraction.status); // \"ready\" once discovery finishes\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\nextraction = riveter.extractions.get(\"ext_YOUR_EXTRACTION_ID\")\nprint(extraction.status)  # \"ready\" once discovery finishes\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\nextraction = riveter.extractions.get(\"ext_YOUR_EXTRACTION_ID\")\nputs extraction.status # \"ready\" once discovery finishes\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\nextraction, err := client.Extractions.Get(context.Background(), \"ext_YOUR_EXTRACTION_ID\")\nfmt.Println(extraction.Status) // \"ready\" once discovery finishes\n"}],"tags":["Extractions"],"parameters":[{"name":"id","in":"path","required":true,"description":"The extraction id (ext_...)","schema":{"type":"string"}}],"responses":{"200":{"description":"Extraction status and definition","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Extraction"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/monitors":{"post":{"summary":"create monitor","description":"Create a **monitor**: a schedule that re-runs an enrichment daily, weekly, or monthly and can POST results (or only changes) to a webhook.\n","operationId":"createMonitor","x-mcp-open-world":true,"x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\nconst monitor = await riveter.monitors.create({\n  enrichment_id: \"enr_YOUR_ENRICHMENT_ID\",\n  cadence: \"daily\",\n  minute: 0,\n  hour: 9,\n  timezone: \"America/New_York\",\n  webhook_url: \"https://your-server.com/webhook\",\n});\nconsole.log(monitor.id, monitor.next_run_at);\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\nmonitor = riveter.monitors.create(\n    enrichment_id=\"enr_YOUR_ENRICHMENT_ID\",\n    cadence=\"daily\",\n    minute=0,\n    hour=9,\n    timezone=\"America/New_York\",\n    webhook_url=\"https://your-server.com/webhook\",\n)\nprint(monitor.id, monitor.next_run_at)\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\nmonitor = riveter.monitors.create(\n  enrichment_id: \"enr_YOUR_ENRICHMENT_ID\",\n  cadence: \"daily\",\n  minute: 0,\n  hour: 9,\n  timezone: \"America/New_York\",\n  webhook_url: \"https://your-server.com/webhook\"\n)\nputs \"#{monitor.id} #{monitor.next_run_at}\"\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\nmonitor, err := client.Monitors.Create(context.Background(),\n    riveter.CreateMonitorParams{\n        EnrichmentID: \"enr_YOUR_ENRICHMENT_ID\",\n        Cadence:      \"daily\",\n        Minute:       0,\n        Hour:         9,\n        Timezone:     \"America/New_York\",\n        WebhookURL:   \"https://your-server.com/webhook\",\n    })\nfmt.Println(monitor.ID, monitor.NextRunAt)\n"}],"tags":["Monitors"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enrichment_id":{"type":"string","description":"Id of the enrichment to monitor (enr_...)"},"cadence":{"type":"string","enum":["daily","weekly","monthly"],"description":"How often the monitor runs"},"minute":{"type":"integer","minimum":0,"maximum":59,"description":"Minute of the hour to run"},"hour":{"type":"integer","minimum":0,"maximum":23,"description":"Hour of the day to run"},"day_of_week":{"type":"integer","minimum":0,"maximum":6,"description":"Day of the week (0=Sunday, required for weekly)"},"day_of_month":{"type":"integer","minimum":1,"maximum":28,"description":"Day of the month (required for monthly)"},"timezone":{"type":"string","description":"Timezone (e.g. 'UTC', 'America/New_York')"},"webhook_url":{"type":"string","format":"uri","description":"URL to receive results each scheduled run"},"alert_rule":{"type":"string","enum":["each_run","only_on_change"],"description":"When to send alerts (default each_run)"},"output_format":{"type":"string","enum":["current_only","current_and_previous"],"description":"Output format (default current_only)"},"run_immediately":{"type":"boolean","description":"Also run the monitor immediately after creation"},"input":{"$ref":"#/components/schemas/EnrichmentInputData","description":"Optional fixed input data for the monitor"}},"required":["enrichment_id","cadence","minute","hour","timezone"]},"examples":{"daily_monitor":{"summary":"Daily monitor with change alerts","value":{"enrichment_id":"enr_018f5b60-1234-7abc-89ab-0123456789ab","cadence":"daily","hour":9,"minute":0,"timezone":"UTC","alert_rule":"only_on_change","webhook_url":"https://your-server.com/webhook"}}}}}},"responses":{"201":{"description":"Monitor created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Monitor"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/UnprocessableEntity"}}},"get":{"summary":"list monitors","description":"List the account's monitors, newest first.","operationId":"listMonitors","x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\nconst monitors = await riveter.monitors.list();\nfor (const monitor of monitors) {\n  console.log(monitor.id, monitor.schedule_summary);\n}\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\nfor monitor in riveter.monitors.list():\n    print(monitor.id, monitor.schedule_summary)\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\nriveter.monitors.list.each do |monitor|\n  puts \"#{monitor.id} #{monitor.schedule_summary}\"\nend\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\nmonitors, err := client.Monitors.List(context.Background())\nfor _, monitor := range monitors {\n    fmt.Println(monitor.ID, monitor.ScheduleSummary)\n}\n"}],"tags":["Monitors"],"responses":{"200":{"description":"Monitors listed","content":{"application/json":{"schema":{"type":"object","properties":{"monitors":{"type":"array","items":{"$ref":"#/components/schemas/Monitor"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/monitors/{id}":{"get":{"summary":"get monitor","description":"The monitor's schedule, webhook, and next run time.","operationId":"getMonitor","x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\nconst monitor = await riveter.monitors.get(\"mon_YOUR_MONITOR_ID\");\nconsole.log(monitor.enabled, monitor.next_run_at);\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\nmonitor = riveter.monitors.get(\"mon_YOUR_MONITOR_ID\")\nprint(monitor.enabled, monitor.next_run_at)\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\nmonitor = riveter.monitors.get(\"mon_YOUR_MONITOR_ID\")\nputs \"#{monitor.enabled} #{monitor.next_run_at}\"\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\nmonitor, err := client.Monitors.Get(context.Background(), \"mon_YOUR_MONITOR_ID\")\nfmt.Println(monitor.Enabled, monitor.NextRunAt)\n"}],"tags":["Monitors"],"parameters":[{"name":"id","in":"path","required":true,"description":"The monitor id (mon_...)","schema":{"type":"string"}}],"responses":{"200":{"description":"The monitor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Monitor"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"summary":"update monitor","description":"Pause, resume, or repoint a monitor. `enabled: false` pauses, `enabled: true` resumes; `webhook_url` replaces the delivery URL.\n","operationId":"updateMonitor","x-mcp-open-world":true,"x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\n// Pause the monitor:\nconst monitor = await riveter.monitors.update(\"mon_YOUR_MONITOR_ID\", {\n  enabled: false,\n});\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\n# Pause the monitor:\nmonitor = riveter.monitors.update(\"mon_YOUR_MONITOR_ID\", enabled=False)\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\n# Pause the monitor:\nmonitor = riveter.monitors.update(\"mon_YOUR_MONITOR_ID\", enabled: false)\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\n// Pause the monitor (Enabled is a pointer so `false` still serializes):\nenabled := false\nmonitor, err := client.Monitors.Update(context.Background(), \"mon_YOUR_MONITOR_ID\",\n    riveter.UpdateMonitorParams{Enabled: &enabled})\n"}],"tags":["Monitors"],"parameters":[{"name":"id","in":"path","required":true,"description":"The monitor id (mon_...)","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean","description":"false pauses the monitor, true resumes it"},"webhook_url":{"type":"string","format":"uri"}}},"examples":{"pause":{"summary":"Pause","value":{"enabled":false}},"resume":{"summary":"Resume","value":{"enabled":true}}}}}},"responses":{"200":{"description":"The updated monitor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Monitor"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/UnprocessableEntity"}}}},"/monitors/{id}/runs":{"get":{"summary":"list monitor runs","description":"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`.\n","operationId":"listMonitorRuns","x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\nconst page = await riveter.monitors.runs(\"mon_YOUR_MONITOR_ID\");\nfor await (const run of page) { // auto-pages through every result\n  console.log(run.id, run.status);\n}\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\npage = riveter.monitors.runs(\"mon_YOUR_MONITOR_ID\")\nfor run in page.auto_paging_iter():  # pages through every result\n    print(run.id, run.status)\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\npage = riveter.monitors.runs(\"mon_YOUR_MONITOR_ID\")\npage.auto_paging_each do |run| # pages through every result\n  puts \"#{run.id} #{run.status}\"\nend\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\nctx := context.Background()\npage, err := client.Monitors.Runs(ctx, \"mon_YOUR_MONITOR_ID\", nil)\nfor {\n    for _, run := range page.Runs {\n        fmt.Println(run.ID, run.Status)\n    }\n    if !page.HasNextPage() {\n        break\n    }\n    page, err = page.NextPage(ctx)\n}\n"}],"tags":["Monitors"],"parameters":[{"name":"id","in":"path","required":true,"description":"The monitor id (mon_...)","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["pending","enqueued","processing","success","stopped"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":1}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","default":25,"maximum":100}}],"responses":{"200":{"description":"Monitor runs listed","content":{"application/json":{"schema":{"type":"object","properties":{"monitor_id":{"type":"string"},"runs":{"type":"array","items":{"$ref":"#/components/schemas/RunListItem"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/quick_search":{"post":{"summary":"quick search","description":"Run a web search and get structured results back **synchronously** — the response is the run with the results already in `output` (no polling, no webhook). Optionally filter to a date range with `date_start` / `date_end` (format `YYYY-MM-DD`); if only `date_start` is given, `date_end` defaults to today.\n\nThe result is also stored on the run, so it stays re-fetchable at [GET /runs/{id}/result](#tag/runs/get/runs/{id}/result).\n\nFor bulk searches — up to **100,000** per request, async with `webhook_url` support — use the legacy [POST /v1/web_search](./openapi.legacy.yaml) endpoint.\n\n## Quick example\n```bash\ncurl -X POST https://api.riveterhq.com/v1/quick_search \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"query\": \"latest OpenAI news\"}'\n```\n\n## Credit costs\n- **0.04 credits** per search.\n","operationId":"quickSearch","x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\nconst run = await riveter.quickSearch({ query: \"Riveter data enrichment\" });\nconsole.log(run.output); // synchronous — results are already here\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\nrun = riveter.quick_search(\"Riveter data enrichment\")\nprint(run.output)  # synchronous — results are already here\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\nrun = riveter.quick_search(query: \"Riveter data enrichment\")\nputs run.output # synchronous — results are already here\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\nrun, err := client.QuickSearch(context.Background(),\n    riveter.QuickSearchParams{Query: \"Riveter data enrichment\"})\nfmt.Println(string(run.Output)) // synchronous — results are already here\n"}],"tags":["Tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string","description":"The search query (simpler is better)"},"date_start":{"type":"string","description":"Optional start date filter, format YYYY-MM-DD"},"date_end":{"type":"string","description":"Optional end date filter, format YYYY-MM-DD. Defaults to today if date_start is set"},"run_key":{"type":"string","maxLength":255,"pattern":"^[A-Za-z0-9._~-]+$","description":"Optional idempotency key (becomes the run id \"run_<run_key>\")"}},"required":["query"]},"examples":{"simple_search":{"summary":"A simple search","value":{"query":"latest OpenAI news"}},"date_filtered_search":{"summary":"A search filtered to a date range","value":{"query":"OpenAI GPT-4o mini","date_start":"2024-07-01","date_end":"2024-07-31"}}}}}},"responses":{"200":{"description":"Search completed — the run with the results in `output`","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Run"},{"type":"object","properties":{"output":{"description":"The search results: `{ \"results\": [{ \"title\", \"link\", \"snippet\" }, ...], \"knowledge_graph\"? }`","type":"object"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/UnprocessableEntity"}}}},"/search_agent":{"post":{"summary":"search agent","description":"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.\n\nThis 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.\n\nThe 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.\n\nPass `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\"`.\n\n## Quick example\n```bash\ncurl -X POST https://api.riveterhq.com/v1/search_agent \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"Who is the current CEO of Anthropic, and when did they take the role?\"}'\n```\n\n## Credit costs\n- **1 credit** per call (same as one agent-mode enrichment cell), charged when the agent completes. Failed runs are not charged.\n","operationId":"searchAgent","tags":["Tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"prompt":{"type":"string","maxLength":50000,"description":"The question or task for the agent"},"output_schema":{"type":"object","description":"Optional JSON Schema object for the answer, e.g. `{\"type\": \"object\", \"properties\": {\"ceo_name\": {\"type\": \"string\"}}}`. When set, `output.result` is an object matching this schema."},"wait":{"type":"integer","minimum":0,"maximum":50,"description":"Seconds to hold this request waiting for the answer (default and max 50). Pass 0 to return immediately and poll GET /runs/{id}/result instead."},"run_key":{"type":"string","maxLength":255,"pattern":"^[A-Za-z0-9._~-]+$","description":"Optional idempotency key (becomes the run id \"run_<run_key>\")"}},"required":["prompt"]},"examples":{"free_text_question":{"summary":"A free-text question","value":{"prompt":"Who is the current CEO of Anthropic, and when did they take the role?"}},"structured_answer":{"summary":"A structured answer via output_schema","value":{"prompt":"Find the founding year and headquarters city of Anthropic","output_schema":{"type":"object","properties":{"founding_year":{"type":"integer"},"headquarters_city":{"type":"string"}}}}}}}}},"responses":{"201":{"description":"The run — with the answer in `output.result` when it finished within `wait`, or `status: processing` and `output: null` when the agent is still working","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Run"},{"type":"object","properties":{"output":{"type":["object","null"],"description":"`{ \"result\": <string or object> }` once the run finishes; null while it is still processing"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/UnprocessableEntity"}}}},"/scrape":{"post":{"summary":"scrape","description":"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).\n\n## Quick example\n```bash\n  curl -X POST https://api.riveterhq.com/v1/scrape \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"url\": \"https://example.com\"}'\n```\n\n## Credit costs\n- **With proxy**: 1/5 credit (0.20 credits)\n- **Without proxy**: 1/20 credit (0.05 credits)\n- **From cache**: 1/100 credit (0.01 credits)\n\n## Proxy usage\nScraping 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').\n\n## Caching\nRecently scraped pages are cached to save credits (0.01 credits on a cache hit). Set `skip_cache: true` to always fetch fresh content.\n","operationId":"scrape","x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\nconst page = await riveter.scrape({ url: \"https://example.com\" });\nconsole.log(page.text); // synchronous — no run to poll\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\npage = riveter.scrape(\"https://example.com\")\nprint(page.text)  # synchronous — no run to poll\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\npage = riveter.scrape(url: \"https://example.com\")\nputs page.text # synchronous — no run to poll\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\npage, err := client.Scrape(context.Background(),\n    riveter.ScrapeParams{URL: \"https://example.com\"})\nfmt.Println(page.Text) // synchronous — no run to poll\n"}],"tags":["Tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"The URL to scrape"},"proxy_country_code":{"type":"string","description":"Optional two-character country code for proxy (e.g. 'us', 'gb', 'de')","pattern":"^[a-z]{2}$"},"skip_cache":{"type":"boolean","description":"Set to true to bypass cache and always fetch fresh content","default":false}},"required":["url"]}}}},"responses":{"200":{"description":"Webpage scraped successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapeResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/UnprocessableEntity"}}}},"/account":{"get":{"summary":"account","description":"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).\n","operationId":"getAccount","x-codeSamples":[{"lang":"typescript","label":"TypeScript","source":"import { Riveter } from \"riveter-sdk\";\n\nconst riveter = new Riveter(); // uses env RIVETER_API_KEY\nconst info = await riveter.account();\nconsole.log(info.account.credit.balance);\n"},{"lang":"python","label":"Python","source":"from riveter import Riveter\n\nriveter = Riveter()  # uses env RIVETER_API_KEY\ninfo = riveter.account()\nprint(info.account.credit.balance)\n"},{"lang":"ruby","label":"Ruby","source":"require \"riveter\"\n\nriveter = Riveter::Client.new # uses env RIVETER_API_KEY\ninfo = riveter.account\nputs info.account.credit.balance\n"},{"lang":"go","label":"Go","source":"import riveter \"github.com/riveterhq/riveter-go\"\n\nclient, err := riveter.NewClient() // uses env RIVETER_API_KEY\ninfo, err := client.Account(context.Background())\nfmt.Println(info.Account.Credit.Balance)\n"}],"tags":["Account"],"responses":{"200":{"description":"Account information retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"request_status":{"type":"string","enum":["success"]},"message":{"type":"string"},"account":{"$ref":"#/components/schemas/Account"},"api_key_info":{"$ref":"#/components/schemas/ApiKeyInfo"}},"required":["request_status","message","account","api_key_info"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}}},"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"API_KEY","description":"API key authentication. Use 'Bearer YOUR_API_KEY' in the Authorization header.","x-scalar-secret-token":"YOUR_API_KEY"}},"schemas":{"Run":{"type":"object","description":"The uniform shape for every run, returned by kickoff endpoints and all /runs endpoints.\nRelated resource ids (enrichment_id, dataset_id, extraction_id, monitor_id) appear when they\napply to the run; kickoff responses may add a few endpoint-specific fields.\n","properties":{"id":{"type":"string","description":"The run id (run_...)"},"type":{"type":"string","enum":["enrichment","dataset_build","extraction","scrape","quick_search","search_agent"],"description":"What kind of run this is"},"status":{"type":"string","enum":["pending","enqueued","processing","success","stopped"]},"progress":{"$ref":"#/components/schemas/RunProgress"},"credits_used":{"type":"number","description":"Credits consumed so far"},"app_url":{"type":"string","format":"uri","description":"Link to view this run in the Riveter app"},"result_url":{"type":"string","format":"uri","description":"Where to fetch the run's output"},"started_at":{"type":["string","null"],"format":"date-time"},"finished_at":{"type":["string","null"],"format":"date-time"},"error":{"type":["object","null"],"description":"Null unless the run hit an error","properties":{"type":{"type":"string"},"message":{"type":"string"}}},"enrichment_id":{"type":"string","description":"Present when the run belongs to an enrichment"},"enrichment_name":{"type":"string"},"dataset_id":{"type":"string","description":"Present on dataset-build runs"},"extraction_id":{"type":"string","description":"Present on extraction runs"},"monitor_id":{"type":"string","description":"Present on monitor-scheduled runs"},"webhook_url":{"type":"string","format":"uri","description":"Present when the run has a webhook configured"}},"required":["id","type","status","progress","result_url"],"example":{"id":"run_018f6a70-1234-7abc-89ab-0123456789ab","type":"enrichment","status":"processing","progress":{"percent_complete":40,"estimated_seconds_remaining":90,"elapsed_seconds":60,"completed_cells":4,"total_cells_expected":10,"not_found_cells":0},"credits_used":2.5,"app_url":"https://app.riveterhq.com/runs/run_018f6a70-1234-7abc-89ab-0123456789ab","result_url":"https://api.riveterhq.com/v1/runs/run_018f6a70-1234-7abc-89ab-0123456789ab/result","started_at":"2026-01-15T12:00:00Z","finished_at":null,"error":null,"enrichment_id":"enr_018f5b60-1234-7abc-89ab-0123456789ab","enrichment_name":"My Enrichment"}},"RunProgress":{"type":"object","description":"Completion estimate. Cell-based runs (enrichment, quick_search) also report cell counts.","properties":{"percent_complete":{"type":["number","null"]},"estimated_seconds_remaining":{"type":["number","null"]},"elapsed_seconds":{"type":["number","null"]},"completed_cells":{"type":"integer","description":"Cell-based runs only"},"total_cells_expected":{"type":"integer","description":"Cell-based runs only"},"not_found_cells":{"type":"integer","description":"Cell-based runs only"}}},"RunListItem":{"type":"object","description":"The slim run shape used by GET /runs and GET /monitors/{id}/runs.","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["enrichment","dataset_build","extraction","scrape","quick_search","search_agent"]},"status":{"type":"string","enum":["pending","enqueued","processing","success","stopped"]},"enrichment_id":{"type":["string","null"]},"enrichment_name":{"type":["string","null"]},"row_count":{"type":["integer","null"]},"credits_used":{"type":"number"},"error":{"type":["object","null"],"properties":{"type":{"type":"string"},"message":{"type":"string"}}},"created_at":{"type":"string","format":"date-time"},"started_at":{"type":["string","null"],"format":"date-time"},"finished_at":{"type":["string","null"],"format":"date-time"},"app_url":{"type":"string","format":"uri"},"result_url":{"type":"string","format":"uri"}}},"Pagination":{"type":"object","properties":{"page":{"type":"integer"},"per_page":{"type":"integer"},"total_count":{"type":"integer"},"total_pages":{"type":"integer"}}},"EnrichmentInputData":{"type":"object","description":"Keys are your source-data column headers. Values are arrays of strings (one per row).\nAny column header name is allowed; all input columns must have the same array length.\nRow caps: 10,000 rows with enrichment_id, 1,000 rows with an inline config.\n","additionalProperties":{"type":"array","description":"One string per row (all input columns must have the same array length)","items":{"type":"string"},"maxItems":10000},"example":{"Company Name":["Acme Corp","Tech Solutions Inc"],"Website":["acme.com","techsolutions.com"]}},"FormatDetails":{"type":"object","description":"Format-specific options. Valid keys depend on the column `format`.\nOnly include keys that apply to your chosen format.\n","properties":{"options":{"type":"array","items":{"type":"string"},"description":"tag — allowed tag values (required for tag format)"},"allow_multiple":{"type":"boolean","description":"tag — allow selecting more than one tag"},"descriptions":{"type":"object","description":"tag — optional map from tag value to description (keys must be in `options`)"},"decimal_places":{"type":"integer","description":"number — decimal places to round to"}}},"EnrichmentOutputColumnConfig":{"type":"object","description":"Per-column enrichment config. **Agent mode** (default): include `prompt` and `contexts`.\n**Tool-only mode**: set `tool` and its parameters (do not use `prompt`/`contexts`).\n","properties":{"prompt":{"type":"string","description":"Agent instructions for this column (agent mode)"},"contexts":{"type":"array","description":"Column headers used as input context (agent mode)","items":{"type":"string"}},"tools":{"type":"array","description":"Agent tools: web_search, scrape, pdf, image, etc.","items":{"type":"string"}},"format":{"type":"string","enum":["text","number","url","email","tag","date","json","boolean"]},"format_details":{"$ref":"#/components/schemas/FormatDetails"},"run_when":{"type":"string","enum":["always","any_filled","all_filled","dynamic"],"description":"When this column should run per row. `always` (default), `any_filled` / `all_filled`\n(based on the column's `contexts`), or `dynamic` (rule-based — requires `run_when_config`).\n"},"run_when_config":{"type":"object","description":"Rule-based run condition, required when `run_when` is `dynamic`. The column runs for a row\nonly when its rules match (`match_mode: all` = every rule must match, `any` = at least one).\n","properties":{"match_mode":{"type":"string","enum":["all","any"]},"rules":{"type":"array","items":{"type":"object","properties":{"column":{"type":"string"},"condition":{"type":"string","enum":["is_empty","is_not_empty","text_contains","text_does_not_contain","text_starts_with","text_ends_with","text_is_exactly"]},"value":{"type":"string"}},"required":["column","condition"]}}}},"tool":{"type":"string","description":"Tool-only mode: scrape, web_search, pdf, image, code, LinkedIn tools, etc."},"url":{"type":"string","description":"Column header or static URL (tool-only)"},"query":{"type":"string","description":"Column header or static query (tool-only, web_search)"},"date_start":{"type":"string","description":"Optional start date for filtering search results. Format: YYYY-MM-DD (tool-only, web_search)"},"date_end":{"type":"string","description":"Optional end date filter. Format: YYYY-MM-DD. Defaults to today if date_start is provided (tool-only, web_search)"},"code":{"type":"string","description":"JavaScript source (tool-only, code tool)"},"args":{"type":"object","description":"Named arguments for the code tool (tool-only). Keys are names referenced in your JavaScript\n(e.g. `args.first`). Values are column headers (dynamic per row) or static strings.\n"},"proxy_country_code":{"type":"string"},"wait_longer":{"type":"boolean"},"skip_cache":{"type":"boolean"},"delete":{"type":"boolean","description":"PATCH /enrichments/{id} only — set true to remove this column"}}},"EnrichmentOutputSpec":{"type":"object","description":"Keys are output column headers. Values are per-column configuration objects.\nAny output column name is allowed; see the per-column schema for all supported fields.\n","additionalProperties":{"$ref":"#/components/schemas/EnrichmentOutputColumnConfig"},"example":{"Employee Count":{"prompt":"Find the number of employees at this company","contexts":["Company Name","Website"],"format":"number"},"Industry":{"prompt":"What industry is this company in?","contexts":["Company Name"],"format":"tag","format_details":{"options":["SaaS","Fintech","Healthcare","Other"]}}}},"Extraction":{"type":"object","properties":{"id":{"type":"string","description":"Extraction id (ext_...)"},"name":{"type":"string"},"status":{"type":"string","enum":["discovering","ready","discovery_failed"]},"app_url":{"type":"string","format":"uri"},"starting_url":{"type":"string","format":"uri"},"goal_description":{"type":"string"},"output_record_json_schema":{"type":["object","string","null"],"description":"The record schema you provided"},"required_keys":{"type":"array","items":{"type":"string"}},"locked":{"type":"boolean","description":"Locked plans can't be re-discovered"},"validation_passing":{"type":["boolean","null"],"description":"Whether the last discovery validation passed"},"discovered_at":{"type":["string","null"],"format":"date-time"},"run_credits_required":{"type":"number","description":"Credits charged per run"}}},"Monitor":{"type":"object","properties":{"id":{"type":"string","description":"Monitor id (mon_...)"},"name":{"type":"string"},"enabled":{"type":"boolean"},"cadence":{"type":"string","enum":["daily","weekly","monthly"]},"minute":{"type":"integer"},"hour":{"type":"integer"},"day_of_week":{"type":["integer","null"]},"day_of_month":{"type":["integer","null"]},"timezone":{"type":"string"},"webhook_url":{"type":["string","null"],"format":"uri"},"alert_rule":{"type":"string","enum":["each_run","only_on_change"]},"output_format":{"type":"string","enum":["current_only","current_and_previous"]},"next_run_at":{"type":["string","null"],"format":"date-time"},"schedule_summary":{"type":"string","description":"Human-readable schedule (e.g. \"Daily at 9:00 UTC\")"},"enrichment_id":{"type":"string"},"enrichment_name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"has_input":{"type":"boolean","description":"Whether the monitor carries fixed input data"}}},"ScrapeResponse":{"type":"object","description":"Synchronous scrape result (legacy request_status format — endpoint unchanged from the legacy API).","properties":{"request_status":{"type":"string","enum":["success"]},"text":{"type":"string","description":"The extracted text content from the webpage"},"url":{"type":"string","format":"uri","description":"The URL that was scraped"},"base_url_for_links":{"type":"string","description":"The base URL for resolving relative links"},"status_code":{"type":"integer","description":"The HTTP status code returned by the server"},"possibly_blocked":{"type":"boolean","description":"Present when the page may be blocked by anti-scraping measures"},"credit_used":{"type":"number","description":"The number of credits consumed"},"riveter_app_link":{"type":"string","format":"uri","description":"Direct link to view this scrape in the Riveter application"}}},"Account":{"type":"object","properties":{"uuid":{"type":"string","format":"uuid","description":"Unique identifier for the account"},"name":{"type":"string","description":"Account name"},"plan":{"type":"string","enum":["free","starter","advanced","pro","enterprise"],"description":"Current billing plan"},"credit":{"$ref":"#/components/schemas/Credit"}},"required":["uuid","name","plan","credit"]},"Credit":{"type":"object","properties":{"count":{"type":"integer","description":"Current credit count"},"max":{"type":"integer","description":"Maximum credits available"},"balance":{"type":"integer","description":"Remaining credit balance"}},"required":["count","max","balance"]},"ApiKeyInfo":{"type":"object","properties":{"name":{"type":"string","description":"Name of the API key"},"last_used_at":{"type":["string","null"],"format":"date-time","description":"When the API key was last used"},"created_by":{"$ref":"#/components/schemas/User"}},"required":["name","last_used_at","created_by"]},"User":{"type":"object","properties":{"uuid":{"type":"string","format":"uuid","description":"User's unique identifier"},"name":{"type":"string","description":"User's full name"},"email":{"type":"string","format":"email","description":"User's email address"}},"required":["uuid","name","email"]},"Error":{"type":"object","description":"The uniform error body (all endpoints except 401 auth failures).","properties":{"error":{"type":"object","properties":{"type":{"type":"string","description":"Machine-readable error type (bad_request, not_found, forbidden, duplicate_run_key, insufficient_credits, validation, not_implemented, ...)"},"message":{"type":"string","description":"Human-readable explanation"},"details":{"description":"Optional extra context (e.g. per-field validation errors)"}},"required":["type","message"]}},"required":["error"],"example":{"error":{"type":"not_found","message":"No run found with id run_018f6a70-..."}}},"AuthError":{"type":"object","description":"Authentication failures come from the shared auth layer and use the legacy shape.","properties":{"request_status":{"type":"string","enum":["error"]},"message":{"type":"string"},"error_type":{"type":"string","enum":["unauthorized"]}},"example":{"request_status":"error","message":"Invalid or missing API key","error_type":"unauthorized"}}},"responses":{"BadRequest":{"description":"The request is malformed or names a conflicting parameter combination","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"Missing or invalid API key (legacy-shaped body — see the AuthError schema)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"Forbidden":{"description":"The API key's account may not access this resource or endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No resource with that id on this account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"Duplicate run_key or a run already in progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UnprocessableEntity":{"description":"The request is valid but can't be executed (e.g. insufficient credits, validation failure)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"tags":[{"name":"Runs","description":"The uniform lifecycle for every async operation — status, results, stop.\n\n**The run** (returned by kickoffs and every `/runs` endpoint):\n\n```json\n{\n  \"id\": \"run_018f6a70-1234-7abc-89ab-0123456789ab\",\n  \"type\": \"enrichment\",\n  \"status\": \"processing\",\n  \"progress\": {\n    \"percent_complete\": 40,\n    \"estimated_seconds_remaining\": 90,\n    \"elapsed_seconds\": 60,\n    \"completed_cells\": 4,\n    \"total_cells_expected\": 10,\n    \"not_found_cells\": 0\n  },\n  \"credits_used\": 2.5,\n  \"app_url\": \"https://app.riveterhq.com/runs/run_018f6a70-...\",\n  \"result_url\": \"https://api.riveterhq.com/v1/runs/run_018f6a70-.../result\",\n  \"started_at\": \"2026-01-15T12:00:00Z\",\n  \"finished_at\": null,\n  \"error\": null,\n  \"enrichment_id\": \"enr_018f5b60-...\",\n  \"enrichment_name\": \"My Enrichment\"\n}\n```\n\nRelated resource ids (`enrichment_id`, `dataset_id`, `extraction_id`, `monitor_id`) appear when they apply to the run. Kickoff responses may carry a few extra fields (e.g. `dataset_id`, `max_items` on dataset builds).\n"},{"name":"Enrich","description":"Enrich data and manage saved enrichment configurations"},{"name":"Datasets","description":"Generate rows from prompts, specs, or reusable templates"},{"name":"Extractions","description":"Reusable site scrape/extract recipes and their runs"},{"name":"Tools","description":"Synchronous and quick utilities — web search and scraping."},{"name":"Monitors","description":"Scheduled enrichment runs with webhooks"},{"name":"Account","description":"Account and API key information"}]}