Enrich

Fill in new columns for rows of data. The rows come from exactly one of dataset_id — a dataset Riveter keeps, the preferred way — or input, rows sent inline for a one-off run.

Preferred: fill a dataset (dataset_id)

Put the rows in a dataset first — POST /datasets with rows (objects keyed by input column name) and the output columns to add, either attributes (their names; Riveter creates the dataset's enrichment from them) or the enrichment_id of a saved enrichment. That is free. Then fill it:

curl -X POST "https://api.riveterhq.com/v1/datasets" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Q4 targets",
    "rows": [{ "Company": "Apple", "Website": "apple.com" }, { "Company": "Shopify", "Website": "shopify.com" }],
    "attributes": ["CEO", "Employee Count", "Industry"]
  }'

curl -X POST "https://api.riveterhq.com/v1/enrich" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "dataset_id": "ds_YOUR_DATASET_ID" }'

The dataset keeps the rows and every filled cell: one AI agent researches each row's columns together, a later call fills only what is new or changed (every pending, stale, or failed cell by default), rows are added, re-run, exported, and read back at any time (GET /datasets/{id}/rows), and the grid is in the Riveter app.

The columns come from the dataset's enrichment, so no column config is sent (an enrichment_id is accepted only when it is that enrichment). columns (output column names), rows (row ids), and positions narrow the scope, and force: true re-runs cells that are already filled. prompt + attributes fills the named columns, adding the ones the dataset does not have yet (a dataset without an enrichment gets one from the prompt; an existing enrichment keeps its own task prompt, and the new columns are typed from their names). An output spec is a 400 — set a column's prompt, schema, or tool with PATCH /datasets/{id} first.

Inline rows (input)

For a one-off run whose rows you do not need to keep. The rows come in the request and the results come back on the run only (output, columnar); the rows live on a single-run dataset that expires. The same engine fills them — one AI agent researches each row's columns together. input is a JSON object in columnar form:

  • Keys are column headers.
  • Values are arrays of strings. Every array must be the same length.
  • Each position across the arrays is one row.

For example, { "Company": ["Apple", "Google"], "Website": ["apple.com", "google.com"] } is two rows:

CompanyWebsite
Appleapple.com
Googlegoogle.com

With input, tell Riveter what columns to add with exactly one of:

  1. A saved enrichment (enrichment_id) — fixed, tested config, the most consistent results.
  2. A prompt + attributes — describe the columns in natural language.
  3. A full output spec (output) — define each column exactly.

1. run an existing enrichment (enrichment_id)

Pass the id of a saved enrichment (enr_...). First build and tune it — on a dataset in the Riveter app (the dataset page's API button shows its enrichment_id) or with POST /enrichments — then run it with new rows. The configuration is fixed and tested, so results are the most consistent of the three. Max 10,000 rows per request. Input column headers must match the enrichment's input columns.

curl -X POST "https://api.riveterhq.com/v1/enrich" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "enrichment_id": "enr_YOUR_ENRICHMENT_ID",
    "input": {"Company Name": ["Acme Corp", "Tech Solutions Inc"]}
  }'

2. run from a prompt + attributes

Provide a natural-language prompt — the task the agent follows for every row — and an attributes array of output column names, each typed from its name. No setup. For repeatable results, put the rows in a dataset (above) or save the enrichment once and run it by enrichment_id (option 1). Max 1,000 rows per request, max 20 attributes.

curl -X POST "https://api.riveterhq.com/v1/enrich" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Research each company",
    "attributes": ["CEO", "Employee Count", "Industry"],
    "input": {"Company": ["Apple", "Google"]},
    "webhook_url": "https://your-server.com/webhook"
  }'

3. run from a full output spec

Define each output column: its prompt, an optional output_schema (a JSON Schema the value must match; inferred when omitted and the value is one plain value), and an optional tool to pin (one call of that tool per row is the cell). contexts is accepted and ignored — the agent reads the whole row. Max 1,000 rows per request. See the EnrichmentOutputSpec schema.

curl -X POST "https://api.riveterhq.com/v1/enrich" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "output": {
      "Employee Count": {
        "prompt": "Find the number of employees at this company",
        "output_schema": { "type": "integer" }
      }
    },
    "input": {"Company": ["Apple", "Google"]}
  }'

Scoping a dataset fill

One column on every row that needs it:

curl -X POST "https://api.riveterhq.com/v1/enrich" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "dataset_id": "ds_YOUR_DATASET_ID",
    "columns": ["CEO"]
  }'

rows (row ids) and positions (counted from 1) pick rows, targets is a list of such { columns, rows, positions } boxes in one run, states names the cell states to re-run (not_found, ok, ...), and force: true re-runs every cell in scope. A row is in one fill at a time: fills on disjoint rows run side by side, and one that overlaps a running fill is refused naming the run and the rows.

After the kickoff

The response is a run. Poll GET /runs/{id}, fetch results with GET /runs/{id}/result, or just wait for your webhook_url to be called. A dataset fill's output is { "rows": [...] } — the rows it ran, each with its cells by column name; an inline run's output is columnar, one entry per input row.

post/enrich

Request

Request body

enrichment_idstring

Config source: id of a saved enrichment (enr_...)

outputEnrichmentOutputSpec

Keys are output column headers. Values are per-column configuration objects. Any output column name is allowed that is not an input column. Columns are researched together by one agent per row and need no order.

promptstring

Config source: the task the agent follows for every row (requires attributes)

attributesstring[]

Config source: the output column names, typed from their names (requires prompt). Max 20.

inputEnrichmentInputData

Keys are your source-data column headers. Values are arrays of strings (one per row). Any column header name is allowed; all input columns must have the same array length. Row caps: 10,000 rows with enrichment_id, 1,000 rows with an inline config.

dataset_idstring

Row source: a ds_... id. Fills the dataset's cells with its bound enrichment; no column config with it.

columnsstring[]

With dataset_id: only these output columns (by name). Default: every output column.

rowsstring[]

With dataset_id: only these rows (row_... ids). May be combined with positions. Default: every row.

positionsinteger[]

With dataset_id: only the rows at these positions (from 1, as list_dataset_rows reports them). May be combined with rows.

statesstring[]

With dataset_id: the cell states to run, e.g. ["not_found"] to research the not-found cells again. Default: pending, stale, failed. Not combined with force.

forceboolean

With dataset_id: re-run every cell in scope, whatever its state (the same as states naming every state).

run_keystring

Optional idempotency key, unique per account. Becomes the run id ("run_<run_key>"), so it is limited to letters, digits, and . _ ~ - characters. A duplicate returns 409.

webhook_urlstring uri

URL to POST the results to when the run completes

allow_duplicate_inputboolean

With enrichment_id — allow re-running rows already present in the enrichment

estimate_costboolean

Validate and price the request without running or charging anything; the 200 response is the credit estimate (EstimateCostResult).

max_creditsnumber

Credit ceiling. Refused with 422 credit_cap_exceeded (nothing charged) when the estimate's maximum exceeds it.

Example request

{
  "output": {
    "Employee Count": {
      "prompt": "The current number of employees at this company",
      "output_schema": {
        "type": "integer",
        "minimum": 0
      }
    },
    "Industry": {
      "prompt": "The industry this company is in",
      "output_schema": {
        "type": "string",
        "enum": [
          "SaaS",
          "Fintech",
          "Healthcare",
          "Other"
        ]
      }
    },
    "CEO": {
      "prompt": "The CEO's full name"
    },
    "CEO Email": {
      "prompt": "A work email address for the CEO",
      "output_schema": {
        "type": "string",
        "format": "email"
      }
    }
  },
  "input": {
    "Company Name": [
      "Acme Corp",
      "Tech Solutions Inc"
    ],
    "Website": [
      "acme.com",
      "techsolutions.com"
    ]
  }
}

Response

estimate_cost only — the credit estimate; nothing was started

estimate_costtrue required
type'enrichment' | 'dataset_build' | 'extraction_discovery' | 'extraction' | 'monitor' | 'scrape' | 'quick_search' | 'search_agent' required

What would have been charged for (monitor = one scheduled run of the monitor)

Example response

{
  "estimate_cost": true,
  "type": "enrichment",
  "credit_detail": {
    "estimate": {
      "minimum": 0,
      "maximum": 1920,
      "charged_upfront": false
    },
    "credits_used": 0,
    "credits_remaining": 5000,
    "sufficient_credits": true
  }
}

Changes

    • warning

      removed the request property //

    • warning

      removed the request property //

    • warning

      removed the request property //

    • warning

      removed the request property //

    • warning

      removed the request property //

    • warning

      removed the request property //

    • warning

      removed the request property //

    • warning

      removed the request property //

    • warning

      removed the request property //

    • warning

      removed the request property //

    • warning

      removed the request property //

    • warning

      removed the request property //

    • warning

      removed the request property //

    • warning

      removed the request property //

    • warning

      removed the request property //

    • warning

      removed the optional property from the response with the status

    • info

      added the optional property ////// to the response with the status

    • info

      added the optional property ////// to the response with the status

    • info

      added the optional property ////// to the response with the status

    • info

      added the optional property ////// to the response with the status

    • info

      added the optional property /////// to the response with the status

    • info

      added the optional property /////// to the response with the status

    • info

      added the optional property /////// to the response with the status

    • info

      added the optional property /////// to the response with the status

    • info

      added the optional property /////// to the response with the status

    • info

      added the optional property /////// to the response with the status

    • info

      added the optional property /////// to the response with the status

    • info

      added the optional property /////// to the response with the status

    • info

      added the optional property /////// to the response with the status

    • info

      added the optional property /////// to the response with the status