Receive data
Callback delivery
Receive validated CSV records directly in your application with CSVJetty onData callback delivery, including row-level error handling and idempotency.
Callback delivery keeps imported row data in the browser and hands it directly to your application's onData function. Your app decides where and how to save it.
onData
Callback delivery
<CSVJetty importerKey="YOUR_IMPORTER_KEY" onData={async ({ rows, importId, rowNumbers }) => { console.log(rows); }}> Import contacts</CSVJetty>For callback delivery, onData is required. CSVJetty waits for the returned promise before completing that delivery step. Throw an error when your application could not save the batch. If you are choosing between callbacks and webhooks, see Delivery modes.
Save records through your API
Keep database credentials and authorization logic on your server. Forward the callback payload to an authenticated endpoint owned by your application.
Production callback
<CSVJetty importerKey="YOUR_IMPORTER_KEY" onData={async ({ rows, importId, rowNumbers }) => { const response = await fetch("/api/contacts/import", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ rows, importId, rowNumbers }), });
if (!response.ok) { throw new Error("Could not save contacts."); }
const body = await response.text(); return body ? JSON.parse(body) : undefined; }}> Import contacts</CSVJetty>Validate twice
Reject individual records
Return an errors array to reject specific original CSV rows while allowing the rest of the batch to succeed.
JS
return { errors: [ { row: 2, message: "Email already exists", }, ],};Row numbers start at 1 after the CSV header and retain their original values even when invalid rows have been filtered out.
Import payload
JS
{ importId: "IMPORT_ID", fileName: "contacts.csv", rows: [ { name: "Ada", email: "ada@example.com", }, ], rowNumbers: [1], skippedRows: 0, uploadedFileHeaders: ["Full Name", "Email"], matchedColumnsMap: { name: "Full Name", email: "Email", },}If Include All Unmatched Columns in Import is enabled, each delivered record also includes an _unmatched object containing unmatched source columns. See the full Import payload reference.
Completion events
Use onComplete for UI updates after the importer finishes. It receives{ importId, accepted, rejected }. Use onClose when you need to react to the importer modal closing.