> For the complete documentation index, see [llms.txt](https://docs.scanner.dev/scanner/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.scanner.dev/scanner/using-scanner-complete-feature-reference/developer-tools/api/lookup-tables.md).

# Lookup Tables

## Create (upload) a lookup table file with metadata

<mark style="color:green;">**`POST`**</mark> `/v1/lookup_table_file/upload/tenant/{tenant_id}`

Upload a new lookup table file via multipart form data. Upload supports CSV and MMDB (MaxMind DB) files; the format is auto-detected from the file's contents.

**Path parameters**

| Name                                                 | Type   | Description                      |
| ---------------------------------------------------- | ------ | -------------------------------- |
| `tenant_id` <mark style="color:red;">required</mark> | string | Unique identifier for the tenant |

**Multipart form fields**

| Name                                            | Type   | Description                     |
| ----------------------------------------------- | ------ | ------------------------------- |
| `file` <mark style="color:red;">required</mark> | file   | CSV or MMDB file to upload      |
| `name` <mark style="color:red;">required</mark> | string | Name for the lookup table       |
| `description`                                   | string | Description of the lookup table |

**Example**

```bash
curl $API_BASE/v1/lookup_table_file/upload/tenant/$TENANT_ID \
-H "Authorization: Bearer $API_KEY" \
-X POST \
-F "file=@./employees.csv" \
-F "name=employee_table" \
-F "description=Employee directory lookup"
```

**Response**

Returns the newly created lookup table file's metadata (identical to [Get](#get-a-lookup-table-files-metadata)).

## List lookup table files

<mark style="color:blue;">**`GET`**</mark> `/v1/lookup_table_file`

List all lookup table files for a tenant.

**Query parameters**

| Name                                                 | Type   | Description                                                                                                                                                    |
| ---------------------------------------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `tenant_id` <mark style="color:red;">required</mark> | string | Unique identifier for the tenant                                                                                                                               |
| `pagination[page_size]`                              | number | Maximum number of results to return in a page. Defaults to 50.                                                                                                 |
| `pagination[page_token]`                             | string | Cursor for pagination. Pass back the `next_page_token` returned in a previous response's `pagination`. If omitted, paging starts at the beginning of the list. |

**Example**

```bash
curl -G $API_BASE/v1/lookup_table_file \
--data-urlencode "tenant_id=$TENANT_ID" \
--data-urlencode "pagination[page_size]=50" \
-H "Authorization: Bearer $API_KEY"
```

**Response**

Returns a paginated envelope whose `data.lookup_table_files` is a list of lookup table file summary objects. The `pagination` object carries the `next_page_token` to pass as the next request's `pagination[page_token]`; `next_page_token` is `null` when there are no more pages.

```json
{
  "data": {
    "lookup_table_files": [
      {
        "id": "00000000-0000-0000-0000-000000000001",
        "tenant_id": "00000000-0000-0000-0000-000000000000",
        "name": "employee_table",
        "description": "Employee directory lookup",
        "file_format": "csv",
        "num_rows": 1234,
        "size_bytes": 98765,
        "sync_source": null,
        "created_at": "2026-01-15T12:00:00Z",
        "updated_at": "2026-01-15T12:00:00Z"
      }
    ]
  },
  "pagination": {
    "next_page_token": null
  }
}
```

{% hint style="info" %}
The list endpoint returns summary objects that do not include the `used_by` or `sync_info` fields. Use the Get endpoint to retrieve dependency information for a specific lookup table.
{% endhint %}

## Get a lookup table file's metadata

<mark style="color:blue;">**`GET`**</mark> `/v1/lookup_table_file/{id}`

Get metadata for a specific lookup table file, including dependency information.

**Example**

```bash
curl $API_BASE/v1/lookup_table_file/00000000-0000-0000-0000-000000000001 \
-H "Authorization: Bearer $API_KEY"
```

**Response**

Returns the lookup table file object.

```json
{
  "lookup_table_file": {
    "id": "00000000-0000-0000-0000-000000000001",
    "tenant_id": "00000000-0000-0000-0000-000000000000",
    "name": "employee_table",
    "description": "Employee directory lookup",
    "file_format": "csv",
    "num_rows": 1234,
    "size_bytes": 98765,
    "sync_source": null,
    "sync_info": null,
    "created_at": "2026-01-15T12:00:00Z",
    "updated_at": "2026-01-15T15:45:00Z",
    "used_by": [
      {
        "type": "transformation",
        "id": "vrl_program:00000000-0000-0000-0000-000000000002",
        "name": "enrich_with_employee_data"
      }
    ]
  }
}
```

## Download the raw lookup table file

<mark style="color:blue;">**`GET`**</mark> `/v1/lookup_table_file/{id}/data`

Download the stored file corresponding to the lookup table, in the same format it was uploaded in.

**Example**

```bash
curl $API_BASE/v1/lookup_table_file/00000000-0000-0000-0000-000000000001/data \
-H "Authorization: Bearer $API_KEY"
```

**Response**

The response body is the file, and the `Content-Type` reflects its format — the same format reported by the `file_format` field in the table's metadata (from Get or List), so you can tell which to expect before downloading:

* **CSV** tables (`file_format: "csv"`) return CSV text with `Content-Type: text/csv`.
* **MMDB** tables (`file_format: "mmdb"`) return a binary MaxMind DB file with `Content-Type: application/octet-stream`.

## Preview a lookup table as CSV

<mark style="color:blue;">**`GET`**</mark> `/v1/lookup_table_file/{id}/csv_preview`

Return a CSV preview of the first `limit` rows. The response is always `Content-Type: text/csv`. For MMDB files the records are rendered as a flattened CSV (one row per network).

**Query parameters**

| Name                                             | Type    | Description                                         |
| ------------------------------------------------ | ------- | --------------------------------------------------- |
| `limit` <mark style="color:red;">required</mark> | integer | Maximum number of data rows (excluding the header). |

**Example**

```bash
curl -G $API_BASE/v1/lookup_table_file/00000000-0000-0000-0000-000000000001/csv_preview \
--data-urlencode "limit=10" \
-H "Authorization: Bearer $API_KEY"
```

**Response**

```csv
id,name,email,department
1,Alice Johnson,alice@example.com,Engineering
2,Bob Smith,bob@example.com,Marketing
```

## Update a lookup table file's metadata

<mark style="color:orange;">**`PUT`**</mark> `/v1/lookup_table_file/{id}`

Update a lookup table's editable metadata. Accepts a JSON body.

**Body**

| Name          | Type           | Description                                                        |
| ------------- | -------------- | ------------------------------------------------------------------ |
| `description` | string \| null | New description. Omit to leave unchanged; pass `null` to clear it. |

{% hint style="info" %}
A lookup table's `name` cannot be changed after creation, as it is used as an identifier in lookup table references within VRL scripts. To replace the file's **contents**, use [Replace a lookup table file's data](#replace-a-lookup-table-files-data).
{% endhint %}

**Example**

```bash
curl $API_BASE/v1/lookup_table_file/00000000-0000-0000-0000-000000000001 \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-X PUT \
-d '{"description": "Updated employee directory"}'
```

**Response**

Returns the updated lookup table file object (same shape as [Get](#get-a-lookup-table-files-metadata)).

## Replace a lookup table file's data

<mark style="color:green;">**`POST`**</mark> `/v1/lookup_table_file/{id}/replace_data`

Replace a lookup table file's contents via multipart form data.

**Multipart form fields**

| Name          | Type   | Description                  |
| ------------- | ------ | ---------------------------- |
| `file`        | file   | Replacement CSV or MMDB file |
| `description` | string | Updated description          |

{% hint style="info" %}
A replacement file must match the existing table's format — the file format (CSV or MMDB) cannot be changed after creation.
{% endhint %}

**Example**

```bash
curl $API_BASE/v1/lookup_table_file/00000000-0000-0000-0000-000000000001/replace_data \
-H "Authorization: Bearer $API_KEY" \
-X POST \
-F "file=@./updated_employees.csv"
```

**Response**

Returns the updated lookup table file object (same shape as [Get](#get-a-lookup-table-files-metadata)).

## Delete a lookup table file

<mark style="color:red;">**`DELETE`**</mark> `/v1/lookup_table_file/{id}`

Delete a lookup table file. Deletion is refused if any transformation still references the table (see `used_by`).

**Example**

```bash
curl $API_BASE/v1/lookup_table_file/00000000-0000-0000-0000-000000000001 \
-H "Authorization: Bearer $API_KEY" \
-X DELETE
```

**Response**

Returns the `id` and `tenant_id` for the deleted lookup table file.

```json
{
  "id": "00000000-0000-0000-0000-000000000001",
  "tenant_id": "00000000-0000-0000-0000-000000000000"
}
```

## Response object reference

### LookupTableFile

Returned by Get, Create, Update, and Replace endpoints.

| Field         | Type            | Description                                                               |
| ------------- | --------------- | ------------------------------------------------------------------------- |
| `id`          | string          | Unique identifier                                                         |
| `tenant_id`   | string          | Owning tenant                                                             |
| `name`        | string          | Name of the lookup table (immutable after creation)                       |
| `description` | string \| null  | Optional description                                                      |
| `file_format` | string          | `"csv"` or `"mmdb"` (auto-detected on upload)                             |
| `num_rows`    | integer \| null | Row count for CSV; `null` for MMDB (records are not enumerated)           |
| `size_bytes`  | integer         | Size of the file in bytes                                                 |
| `sync_source` | object \| null  | Managed sync source, if any (see [Sync source](#sync-source))             |
| `sync_info`   | object \| null  | Last successful sync, if applicable: `{ "last_successful_sync": "<ts>" }` |
| `created_at`  | string          | ISO 8601 creation timestamp                                               |
| `updated_at`  | string          | ISO 8601 last update timestamp                                            |
| `used_by`     | array           | Resources depending on this lookup table. Not returned by List.           |

### LookupTableFileSummary

Returned in `data.lookup_table_files` by the List endpoint (omits `used_by` and `sync_info`). All other fields match `LookupTableFile`.

### Sync source

A lookup table can be a plain user upload (`sync_source: null`) or a managed table fed by an external source. When present, `sync_source` is an object:

| Field          | Type    | Description                                            |
| -------------- | ------- | ------------------------------------------------------ |
| `source`       | object  | The source, tagged by `type` (see below)               |
| `is_connected` | boolean | Whether a sync is currently configured for this source |

The `source` object is tagged by `type`:

```json
// Threat intelligence feed
{ "type": "threat_intel", "source": "alien-vault", "indicator_type": "ipv4-addr" }

// GeoIP database
{ "type": "geoip", "source": "ipinfo", "variant": "ipinfo_lite" }
```

So a fully-populated `sync_source` looks like:

```json
"sync_source": {
  "source": {
    "type": "threat_intel",
    "source": "alien-vault",
    "indicator_type": "ipv4-addr"
  },
  "is_connected": true
}
```

### LookupTableFileDependency

Entries in the `used_by` array.

| Field  | Type   | Description                                                                 |
| ------ | ------ | --------------------------------------------------------------------------- |
| `type` | string | Dependency kind. Currently always `"transformation"`.                       |
| `id`   | string | Identifier of the dependent transformation step, e.g. `vrl_program:<uuid>`. |
| `name` | string | Human-readable name of the dependent resource.                              |

## Quick start script

End-to-end example that lists existing lookup tables, creates one, previews it, and deletes it.

This assumes the following environment variables are set:

* `$API_BASE` — Your team API URL (found in Settings > API Keys)
* `$API_KEY` — Your Scanner API key (found in Settings > API Keys)
* `$TENANT_ID` — Your Team ID (found in Settings > General)

For details on authentication, see [API](/scanner/using-scanner-complete-feature-reference/developer-tools/api.md).

{% code title="lookup\_table\_demo.sh" %}

```bash
#!/usr/bin/env bash
set -euo pipefail

# --- prerequisites ---
if ! command -v jq &>/dev/null; then
  echo "Error: jq is required but not installed." >&2
  exit 1
fi

# --- configuration (all must be set as env vars) ---
: "${API_BASE:?Set API_BASE to your API URL (from Settings > API Keys)}"
: "${API_KEY:?Set API_KEY to your API key (from Settings > API Keys)}"
: "${TENANT_ID:?Set TENANT_ID to your Team ID (from Settings > General)}"

AUTH_HEADER="Authorization: Bearer ${API_KEY}"
BASE="${API_BASE}/v1/lookup_table_file"

# --- temp directory with cleanup ---
TMPDIR="$(mktemp -d)"
trap 'rm -rf "${TMPDIR}"' EXIT

# --- create a small sample CSV ---
CSV_FILE="${TMPDIR}/example_lookup_table.csv"
cat > "${CSV_FILE}" <<'CSV'
username,department,role
alice,engineering,admin
bob,marketing,viewer
charlie,security,analyst
CSV

echo "=== Listing existing lookup tables ==="
curl -sf -G "${BASE}" \
  --data-urlencode "tenant_id=${TENANT_ID}" \
  -H "${AUTH_HEADER}" | jq .
echo

echo "=== Uploading sample lookup table ==="
CREATE_RESPONSE=$(curl -sf -X POST "${BASE}/upload/tenant/${TENANT_ID}" \
  -H "${AUTH_HEADER}" \
  -F "file=@${CSV_FILE}" \
  -F "name=api_docs_example_$(date +%s)" \
  -F "description=Example lookup table created by quick-start script")

echo "${CREATE_RESPONSE}" | jq .

LOOKUP_TABLE_ID=$(echo "${CREATE_RESPONSE}" | jq -r '.lookup_table_file.id')
echo
echo "Created lookup table: ${LOOKUP_TABLE_ID}"
echo

echo "View in Scanner:"
echo "  https://app.scanner.dev/teams/${TENANT_ID}/library/lookup-tables#id=${LOOKUP_TABLE_ID}"
echo

echo "=== Fetching lookup table metadata ==="
curl -sf -X GET "${BASE}/${LOOKUP_TABLE_ID}" \
  -H "${AUTH_HEADER}" | jq .
echo

echo "=== Previewing CSV data ==="
curl -sf -G "${BASE}/${LOOKUP_TABLE_ID}/csv_preview" \
  --data-urlencode "limit=10" \
  -H "${AUTH_HEADER}"
echo
echo

read -rp "Press Enter to delete the lookup table (or Ctrl-C to keep it)..."
echo

echo "=== Deleting lookup table ==="
curl -sf -X DELETE "${BASE}/${LOOKUP_TABLE_ID}" \
  -H "${AUTH_HEADER}" | jq .
echo

echo "Done!"
```

{% endcode %}

## See also

* [Lookup Table Enrichment](/scanner/using-scanner-complete-feature-reference/data-transformation-and-enrichment/lookup-table-enrichment.md) — How to use lookup tables to enrich log data during ingestion
* [Custom Lookup Tables](/scanner/using-scanner-complete-feature-reference/data-transformation-and-enrichment/lookup-table-enrichment/custom-lookup-tables.md) — Setting up and managing custom lookup tables in Scanner


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.scanner.dev/scanner/using-scanner-complete-feature-reference/developer-tools/api/lookup-tables.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
