---
name: voluum-bulk-offer-and-lander-import
description: Prepare and load a batch of offers or landers from a CSV into Voluum using the bulk create and bulk update tools, checking the file before anything is written and reporting exactly what was added or changed. Use when the user has a spreadsheet or CSV of offers or landers to add or update, asks to import, bulk load, mass edit or sync offers or landers, or wants to know what a batch will do before it runs.
---

# Bulk import offers and landers from CSV

This job is about getting a batch right in one pass. The expensive mistakes are a malformed file that half-loads, duplicate rows that create copies of live offers, and an update that quietly overwrites a field the user did not mean to touch. Check the file, confirm the plan, then write once. Single-object creation belongs to a different job; use this one whenever there are more than a handful of rows.

## 1. Confirm the target before touching the file

Ask which Voluum account the batch goes into and whether the user wants to **create**, **update**, or both. Use `bulk_create_offers_csv`, `bulk_create_landers_csv`, `bulk_update_offers_csv` and `bulk_update_landers_csv`; these are separate tools per object type, so keep offers and landers in separate files and separate operations. Confirm which mode the connection is in (read-only or write). In read-only mode none of the bulk tools will work; say so and stop, do not try to route around it.

If the account or workspace is not the one the user named, stop and ask. Do not switch accounts to make a batch fit. Switching the active account or workspace needs the user's explicit yes first.

## 2. Inspect the CSV before sending anything

Read the whole file, not a sample. Check:

- **Header row.** Column names must match what the bulk tool expects for that object. A renamed or missing column is the most common reason a batch fails. Compare the headers against the tool's own parameter description, and where the connector docs or tool description do not say what a column must be called, ask the user rather than guessing.
- **Row count.** Note it. Batches over a few hundred rows are worth splitting so one bad row does not block the rest, and so a failure can be retried in pieces.
- **Duplicates.** Same name, same identifier or same URL on two rows means either a copy error or a real duplicate. Flag every one. Creating a duplicate offer or lander is cheap to write and expensive to clean up.
- **Empty and whitespace cells** in columns that must be filled, leading or trailing spaces in names, and mixed encodings (smart quotes, non-breaking spaces) that break matching.
- **Encoding and delimiter.** Commas inside unquoted fields and semicolon-delimited files silently shift every column. If a row has the wrong number of fields, stop.
- **URLs.** Landers and offer links should be well-formed and use the scheme the user intends. A typo here lives in production traffic.

For update batches, also check that the identifier column is present and unique, because an update keyed on a non-unique field can change more objects than intended.

## 3. Dry-run by reading, not writing

There is no preview step in the bulk tools, so the dry run is your own check on the file: write out a plan table of what the batch will do. For a create batch, state how many new objects will appear and list any rows you suspect are duplicates. For an update batch, list the fields that will change and the old and new values where you can establish the old value from the file or from a read call. Use the read tools that exist for this account to confirm that rows you believe already exist do exist, and that rows you believe are new do not already exist under the same name.

Show the plan to the user and wait for the user's explicit yes before any bulk write. Do not treat a request to "load it" as approval of a plan you have not shown.

## 4. Load in controlled pieces

Once approved, send the batch. If it is large, load a small first chunk (roughly 10 to 20 rows), check the result, then continue in chunks. This turns a silent bulk failure into a small, recoverable one. After each chunk, record what the tool reported: how many rows succeeded, how many failed, and the error text for each failure. Do not assume a call succeeded because it did not raise an error. Confirm with a read.

If a chunk fails partway, stop. Do not re-send the whole file, because that will double-create the rows that already succeeded. Work out which rows are missing and resend only those, after the user's explicit yes to the corrected set.

## 5. Verify and summarise

Read back a sample of the changed or created objects and check that names, URLs and key fields match the file. For updates, confirm the fields that were supposed to change changed and that fields that were not in the file did not change. Then give the user one summary: what was created, what was updated, what failed and why, and what was deliberately left alone.

## Common patterns and traps

- **Header drift.** A file exported from a spreadsheet often has a renamed or extra column. Fix it in the plan, not by guessing at the tool's expected names silently.
- **Create run twice.** A retry after a timeout can recreate everything. Before any retry, read back what exists and send only the missing rows.
- **Update with a blank cell.** A blank may mean "leave unchanged" or "clear this value", depending on the tool. Do not assume; ask, and prefer leaving blank cells out of an update file entirely.
- **Mixing offers and landers in one file.** Split them. A combined file usually fails on the first row of the wrong type.
- **Big-bang loads.** One 2,000-row call that fails at row 1,400 leaves an unclear state. Chunk it.
- **Trusting a success message.** The batch reporting success is not proof the data is right. Read back a sample.
- **Pasted URLs with tracking tokens or secrets.** Note them and do not echo them back in full in your summary.

## Output

```
Target: <account / workspace> | mode: <write confirmed / read-only, stopped>
Batch: <offers | landers> | <create | update> | <N rows in file>
File checks: <headers ok / problems>, <duplicates found: N>, <malformed rows: N>
Plan: <N new objects / N updates touching fields: ...>
Approved by user: <yes, with the plan above>
Loaded: <created N, updated N, failed N> in <chunks>
Failures: <row, reason, retried or pending>
Read-back check: <sample size, what matched, any mismatch>
Left unchanged: <rows or fields deliberately not touched>
Not verified: <anything the read tools could not confirm>
```

## Rules

- Do not send any bulk create or bulk update call without showing the plan and getting the user's explicit yes; a request to "import" is not that yes. Wait for the user's explicit yes before each write batch, and again before any retry of a failed batch.
- Never load a file you have not read in full.
- Do not create objects to replace ones you think are duplicates; flag them and let the user decide.
- Do not switch the active account or workspace to fit the batch. Switching needs the user's explicit yes.
- Do not retry a partially failed batch by resending the whole file.
- Never treat a successful return as verified until a read-back confirms it.

## Done when

- The file has been read in full, its headers, duplicates and malformed rows are reported, and the plan was shown.
- Every write batch ran after the user's explicit yes, in chunks, with per-chunk results recorded.
- A read-back sample matches the file, and the summary lists created, updated, failed and left-alone items.
- Anything not confirmed by a read is listed under "Not verified".
