
# Records Import & Export

Sovrium moves bulk data in and out of tables three ways. **Clipboard** copy/paste between a data-table and a spreadsheet ships today, built on the existing batch and list endpoints. **CSV import** (upload a file to bulk-create records) and **export** (download the current view as CSV or JSON) are designed but not yet available. No configuration is required for any of them.

:::callout
**Status: clipboard ships today; CSV import/export is planned.** Clipboard paste/copy is built on the existing [batch](records-batch) and [list](records-filtering-sorting) endpoints and works now. The CSV import/export endpoints below are a designed, not-yet-shipped surface (the import/export user stories are `Not Started`). This page documents the intended import/export API; the concrete request/response shapes are finalized during implementation.
:::

## CSV import

Upload a CSV file to bulk-load records, with column-to-field mapping, configurable duplicate handling, and per-row error reporting on partial failures.

```
POST /api/tables/:tableId/import
Content-Type: multipart/form-data

Body:
  file              (CSV file)
  mapping           (JSON: { "csvColumn": "tableField" })
  duplicateStrategy ("skip" | "overwrite" | "create")
  uniqueField       (field used to detect duplicates)
```

The response summarizes the outcome and reports per-row errors without failing the whole import:

```json
{
  "imported": 120,
  "skipped": 4,
  "updated": 11,
  "failed": 2,
  "errors": [
    { "row": 17, "field": "email", "error": "Invalid email format" },
    { "row": 92, "field": "amount", "error": "Expected a number" }
  ]
}
```

| Concept                        | Behavior                                                                      |
| ------------------------------ | ----------------------------------------------------------------------------- |
| Column mapping                 | `mapping` maps each CSV column to a table field; unmapped columns are ignored |
| `duplicateStrategy: skip`      | Skip rows whose `uniqueField` already exists                                  |
| `duplicateStrategy: overwrite` | Update the existing matching record                                           |
| `duplicateStrategy: create`    | Always insert a new record                                                    |
| Partial failure                | Valid rows are imported; invalid rows are reported in `errors`                |

Imported records pass the same field-type [validation](table-validation) and field-level [permissions](table-permissions) as a normal create.

## Export

Export the current view of a table — all visible rows, a hand-picked selection, or the same data as JSON for developer tooling.

```
GET /api/tables/:tableId/export?format=csv&viewId=2&filters=JSON&fields=id,name,status
GET /api/tables/:tableId/export?format=json&fields=id,name,status
GET /api/tables/:tableId/export?format=csv&recordIds=1,2,3&fields=id,name,status
```

The response streams the file with an attachment disposition:

```
Content-Type: text/csv            (or application/json)
Content-Disposition: attachment; filename="orders.csv"
```

| Parameter   | Description                                                                          |
| ----------- | ------------------------------------------------------------------------------------ |
| `format`    | `csv` (default) or `json`                                                            |
| `viewId`    | Export the rows of a saved [view](table-views)                                       |
| `filters`   | JSON filter expression (same grammar as [list filtering](records-filtering-sorting)) |
| `fields`    | Comma-separated columns to include                                                   |
| `recordIds` | Export only the named record IDs (a hand-picked selection)                           |

Export honors field-level read permissions — columns the caller cannot read are omitted from the file.

## Clipboard

The data-table component supports spreadsheet-style copy and paste, built on the standard Records endpoints.

| Action        | Behavior                                                            | Underlying endpoint                       |
| ------------- | ------------------------------------------------------------------- | ----------------------------------------- |
| Paste rows    | Paste tab-separated data from Excel/Google Sheets into a data-table | `POST /api/tables/:tableId/records/batch` |
| Paste preview | Preview pasted data with column mapping before committing           | (client-side, then batch create)          |
| Copy rows     | Select rows and copy as tab-separated values to the clipboard       | `GET /api/tables/:tableId/records`        |

Paste maps tab-separated columns onto table fields (with a preview/mapping step so the user can confirm before write), then commits via a single [batch create](records-batch) — keeping the operation atomic. Copy serializes the selected rows' visible columns to TSV.

## Related pages

- [Batch Operations](records-batch) — the atomic bulk-write path clipboard paste uses
- [Filtering, Sorting & Pagination](records-filtering-sorting) — the filter/field grammar export reuses
- [Table Views](table-views) — export a saved view by `viewId`
- [Table Validation](table-validation) — import rows pass field-type validation
- [Table Permissions](table-permissions) — field-level read/write gates import and export
