# Catalog

GET `/sql/v1/catalog`

Returns the queryable surface: every table with its columns, and the allowed function names.

## Request

Takes no body and no query parameters. The only input is the bearer token.

```shell
curl --request GET '{API_URL}/sql/v1/catalog' \
  --header 'Authorization: Bearer <your-api-key>'
```

## Response

The catalog is returned under a `sqlCatalog` object holding `tables` and `functions`. It leaves out the [tables named by dataset RID](https://dev.nominal.io/sql-guides/writing-queries.md#reading-a-whole-dataset).

Each column carries the following metadata:

| Field | Type | Notes |
| --- | --- | --- |
| `name` | string | Column name. |
| `type` | string | Top-level logical type: `TIMESTAMP`, `VARCHAR`, `DOUBLE`, `BIGINT`, `MAP`, `ARRAY`, or `VARIANT`. |
| `nullable` | boolean | Whether the column can hold `NULL`. |
| `dataType` | object | The full type, including what a `MAP` or `ARRAY` holds. Holds one of `scalar` (a type name such as `SQL_CATALOG_SCALAR_TYPE_VARCHAR`), `arrayElement` (the element’s type), or `map` (`key` and `value` types). |

Each function carries the following metadata:

| Field | Type | Notes |
| --- | --- | --- |
| `name` | string | Uppercase function name, e.g. `AVG`, `DATE_BIN`. |
| `kind` | enum | `SQL_CATALOG_FUNCTION_KIND_SCALAR`, `SQL_CATALOG_FUNCTION_KIND_AGGREGATE`, or `SQL_CATALOG_FUNCTION_KIND_WINDOW`. |
| `supportsOver` | boolean | Whether an `OVER` clause is allowed. Always `true` for window functions, which require one. |
| `minArgs` | integer | Minimum number of arguments. |
| `maxArgs` | integer | Maximum number of arguments. Absent for variadic functions. |
| `argumentTypeFamilies` | array | Operand type families (e.g. `NUMERIC`, `DATETIME`, `CHARACTER`, `ANY`), one per argument position up to `maxArgs`. Empty when unknown. |
| `returnTypeFamily` | string | Type family of the result (e.g. `NUMERIC`, `TIMESTAMP`, `CHARACTER`, `BOOLEAN`). Absent when the result type depends on the argument types. |

Fields holding their default value are left out of the JSON: a column with no `nullable` field is not nullable, and a function with no `supportsOver` field doesn’t allow `OVER`.

```json
{
  "sqlCatalog": {
    "tables": [
      {
        "name": "points_double",
        "columns": [
          { "name": "ts", "type": "TIMESTAMP",
            "dataType": { "scalar": "SQL_CATALOG_SCALAR_TYPE_TIMESTAMP" } },
          { "name": "value", "type": "DOUBLE", "nullable": true,
            "dataType": { "scalar": "SQL_CATALOG_SCALAR_TYPE_DOUBLE" } },
          { "name": "channel", "type": "VARCHAR",
            "dataType": { "scalar": "SQL_CATALOG_SCALAR_TYPE_VARCHAR" } },
          { "name": "dataset_rid", "type": "VARCHAR",
            "dataType": { "scalar": "SQL_CATALOG_SCALAR_TYPE_VARCHAR" } },
          { "name": "tags", "type": "MAP",
            "dataType": { "map": {
              "key": { "scalar": "SQL_CATALOG_SCALAR_TYPE_VARCHAR" },
              "value": { "scalar": "SQL_CATALOG_SCALAR_TYPE_VARCHAR" } } } }
        ]
      }
    ],
    "functions": [
      {
        "name": "AVG",
        "kind": "SQL_CATALOG_FUNCTION_KIND_AGGREGATE",
        "supportsOver": true,
        "minArgs": 1,
        "maxArgs": 1,
        "argumentTypeFamilies": ["NUMERIC"],
        "returnTypeFamily": "NUMERIC"
      },
      {
        "name": "DATE_BIN",
        "kind": "SQL_CATALOG_FUNCTION_KIND_SCALAR",
        "minArgs": 3,
        "maxArgs": 3,
        "argumentTypeFamilies": ["ANY", "DATETIME", "DATETIME"]
      }
    ]
  }
}
```

The response is JSON, so it prints safely, but it is long: every table with all its columns, plus the full function allowlist. To make it readable, pipe it through Python’s JSON formatter:

```shell
curl --silent --request GET '{API_URL}/sql/v1/catalog' \
  --header 'Authorization: Bearer <your-api-key>' \
  | python3 -m json.tool
```

To list just the table names:

```shell
curl --silent --request GET '{API_URL}/sql/v1/catalog' \
  --header 'Authorization: Bearer <your-api-key>' \
  | python3 -c "import json,sys; [print(t['name']) for t in json.load(sys.stdin)['sqlCatalog']['tables']]"
```

> **Note**
>
> Because the catalog is served by the REST API, it is the authoritative answer to “what can I query right now.” Prefer it over any static list, including the [Function reference](https://dev.nominal.io/sql-reference/schema/function-reference.md), when the two disagree.

## Next steps

- [Function reference](https://dev.nominal.io/sql-reference/schema/function-reference.md): the allowlist with signatures and restrictions.
- [Writing queries](https://dev.nominal.io/sql-guides/writing-queries.md): query patterns and examples.
