# Your own catalog

Send the export your shop already writes and search it, without writing any configuration first.

Your shop's [export](/docs/reference/glossary#export) goes live as it is: CSV, Excel, a Google Merchant Center feed or JSON. OrbSearch derives the channel, the attributes, the filters and the sorting from the data itself.

This page sends the example store's export, a German Excel CSV, with the stack and the `$key` and `$api` of the [Quickstart](/docs/quickstart#keep-the-management-key-at-hand).

### Publish an empty release

A [release](/docs/reference/glossary#release) without files lets the catalog decide every setting:

```sh title="Terminal"
empty=$(curl -s -H "Authorization: Bearer $key" -H 'Content-Type: application/json' -d '{"files": {}}' $api/releases \
  | jq -r .id)
curl -s -X POST -H "Authorization: Bearer $key" $api/releases/$empty/publish >/dev/null
```

### Send the export

Send the file as your shop writes it, and wait for its [index run](/docs/reference/glossary#index-run):

```sh title="Terminal"
run=$(curl -s -X PUT -H "Authorization: Bearer $key" -H 'Content-Type: text/csv' \
  --data-binary @tests/fixtures/feeds/home/export.csv $api/catalog | jq -r .run.id)
until curl -s -H "Authorization: Bearer $key" $api/index-runs/$run \
  | jq -e '.state | IN("queued", "running") | not' >/dev/null; do sleep 1; done
curl -s -H "Authorization: Bearer $key" $api/index-runs/$run | jq -c '{state, entities: .report.entities}'
```

```json title="Answer: 200 · 19 ms"
{"state":"succeeded","entities":37}
```

The indexer recognizes the format, the encoding and the delimiter from the bytes. The content type only names the file.

### See what it derived

The run's report gives every [derived setting](/docs/reference/glossary#derived-setting) its evidence. Here is why the column `Farbe` (color) became the attribute `color`:

```sh title="Terminal"
curl -s -H "Authorization: Bearer $key" $api/index-runs/$run \
  | jq -c '.report.defaults.reasons[] | select(.setting == "color") | .reason'
```

```json title="Answer: 200 · 17 ms"
{"by":"values","type":"option","share":100,"values":40,"distinct":24}
{"by":"varies","products":14}
{"by":"colors","share":97}
{"by":"faceted"}
```

Its values read as options and differ between a product's variants. Of its values, 97 % are color words, so Grau and Hellgrau (light grey) join the group grey. Pages filter by it, so a query that names a color is read as that filter.

### Search

The quickstart's search works on the export too:

```sh title="Terminal"
curl -s 'http://127.0.0.1:7800/v1/search?query=graues%20Sofa&debug=1' \
  | jq -c '.resolution, [.sections[] | select(.type == "product") | .hits[].entity], .trace.derived'
```

```json title="Answer: 200 · 5.1 ms · release 44136fa3"
{"category":"wohnen/sofas","filters":{"color":"grey"},"text":"","complete":true}
["product:SOFA-ASKA-2","product:SOFA-NIKO-SCHLAF"]
["attributes.json","categories.json","channels.json","ranking.json","rules.json","types.json"]
```

The same two sofas, and `trace.derived` names the six release files the run derived instead of reading them.

## When the defaults are not enough

Write the file you want to decide yourself into the release, such as [`attributes.json`](/docs/reference/release-files/attributes). A file the release writes is yours, and the run keeps deriving the files it leaves out ([Defaults](/docs/releases#defaults-and-zero-configuration) says how the two meet).

The words of an export tell German from English only. A column named for its language, such as `Name FR`, adds that locale; a shop in another language names its locale in [`channels.json`](/docs/reference/release-files/channels).

## Next

- [Importing and mapping](/docs/importing): check what an export becomes before it goes live, and correct how its columns are read.
- [Releases](/docs/releases): write the release files you want to own.
- [Concepts](/docs/concepts): how a catalog and a release meet.
