---
title: "Dry run: apply a column mapping, check every row and find duplicates. Nothing is imported"
method: POST
path: "/api/v1/imports/{id}/preview"
---

# Dry run: apply a column mapping, check every row and find duplicates. Nothing is imported

`POST /api/v1/imports/{id}/preview`

## Request

- Base URL: `http://127.0.0.1:4310`
- URL: `http://127.0.0.1:4310/api/v1/imports/{id}/preview`
- Auth: one of:
  - HTTP bearer
  - API key in cookie `sfb_session`

## Path parameters

- `id` string, required

## Request body

- object
  - `mapping` object
  - `options` object
    - `duplicate_action` 'skip' | 'merge' | 'create'
    - `date_order` 'day_first' | 'month_first'
    - `consent_wording_version` string
    - `balance_mode` 'refuse' | 'replace': Balances: refuse (default) leaves an existing balance alone; replace sets it to the file
    - `create_missing_clients` boolean: Balances, client notes and product purchases: add a client when no client matches (needs a name and an email or phone)
    - `source_name` string: Balances: the old system, for the ledger note (for example Timely). Deposits: Timely shows "Deposit paid in Timely" on the appointment
    - `service_renames` object: Deposits: old service name to the name used here, as the appointment import renamed them. Decides between two appointments on one day
    - `gift_card_product_id` string: Gift voucher balances: the product whose design and default expiry apply
    - `include_cancelled` boolean: Appointments: also import past cancelled appointments as history (left out by default)
    - `accept_clash` boolean: Appointments: save a future appointment that clashes with another or has no free room, like staff "book anyway" (clash_override). It still blocks online booking, the AI receptionist and the waiting list. The preview counts them as clash_overrides. Off by default.
    - `update_existing` boolean: Products: change the price and stock of a product that already exists with the same name or SKU (skipped by default)

## Response `200`

OK

- object

## Other responses

- `400`: Validation error
- `401`: Unauthenticated
- `403`: Forbidden
- `404`: Not found
- `409`: Conflict or invalid state

## Changes

- **2026-10-19** `eb8bf8256417`: 1 info
  - added the new optional request property `options/service_renames`

[Operation history](https://skmtc.dev/scalingfirm/apis/tsf-booking-api/changes/api/v1/imports/:id/preview/post.md)

---

[API](https://skmtc.dev/scalingfirm/apis/tsf-booking-api.md) · [All operations](https://skmtc.dev/scalingfirm/apis/tsf-booking-api/llms.txt) · [OpenAPI document](https://skmtc.dev/scalingfirm/apis/tsf-booking-api/revisions/81704199cd37?raw)
