Import Excel to GraphQL API
How to Import Excel Data into a GraphQL API (Effortlessly)
Developers building SaaS products, no-code platforms, or internal tools frequently need to import structured data from Excel spreadsheets into applications that expose a GraphQL API. This guide shows a pragmatic, developer-friendly flow for converting Excel to JSON, validating and mapping rows, and safely submitting them to GraphQL endpoints — with options to do it yourself or use CSVBox to handle parsing, validation, and delivery. Updated guidance and best practices as of 2026.
The import flow in practice: file → parse → map → validate → batch → submit → handle errors. Focus on accuracy, observability, and developer control.
Who should read this
If you’re a:
- Full-stack engineer integrating spreadsheet uploads with a GraphQL backend
- SaaS founder enabling bulk onboarding or data migration
- Product/dev team building admin imports or internal tooling
- Builder of a no-code/low-code integration that accepts spreadsheets
…you’ll find the examples and patterns here applicable.
Common use cases
- HR platforms letting recruiters upload candidate spreadsheets
- Marketing dashboards ingesting campaign metrics via Excel
- Internal tools performing bulk updates or migrations
- SaaS onboarding flows for users, products, or leads
The core technical challenge is mapping semi-structured spreadsheet rows into the strict JSON input types your GraphQL mutations expect.
How to import Excel to a GraphQL API (manual method)
Below is a concise, practical approach to build an Excel importer for a GraphQL backend: parse the file into JSON, normalize and validate rows, and submit via GraphQL mutations with error handling and batching.
1) Convert Excel (XLSX/XLS/CSV) to JSON
Use a maintained parser such as the xlsx npm package. Prefer reading the file as an ArrayBuffer in modern browsers (readAsBinaryString is deprecated).
Install:
npm install xlsx
Browser-side helper to convert a user-supplied File to JSON rows:
import * as XLSX from 'xlsx';
function excelToJson(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (e) => {
try {
const data = e.target.result; // ArrayBuffer
const workbook = XLSX.read(data, { type: 'array' });
const firstSheet = workbook.SheetNames[0];
const rows = XLSX.utils.sheet_to_json(workbook.Sheets[firstSheet], {
defval: null // keep explicit nulls for empty cells
});
resolve(rows);
} catch (err) {
reject(err);
}
};
reader.onerror = reject;
reader.readAsArrayBuffer(file);
});
}
Notes:
- For CSV files you can use the same package or a streaming CSV parser for large files.
- Use defval: null or similar options to avoid losing empty columns.
- Normalize header casing and trim whitespace (e.g., toLowerCase and trim) so mapping is predictable.
2) Map spreadsheet columns to your GraphQL input
GraphQL inputs are typed — ensure each row maps to the expected input shape.
- Create a deterministic mapping between spreadsheet headers and GraphQL input fields.
- Allow an interactive mapping step for end users (e.g., “Mail” → “email”).
- Normalize date formats and numeric values before submission.
Example GraphQL mutation signature:
mutation BulkCreateItems($input: [ItemInput!]!) {
bulkCreateItems(input: $input) {
id
status
}
}
Transform rows into the input shape, e.g., convert “Amount” string “1,234.56” → number 1234.56 and parse dates into ISO 8601.
3) Validate rows client-side (or server-side)
Validate at multiple levels:
- Structural: required fields present, types correct
- Row-level: email matches regex, numeric ranges, enums valid
- Business rules: uniqueness, foreign-key references (validate on server)
Provide granular feedback to users: highlight invalid rows, show inline errors, and offer download of an errors CSV.
4) Batch requests to GraphQL and handle errors
Avoid sending very large arrays in a single mutation. Batch and retry intelligently.
Simple batching example (client-side):
async function uploadInBatches(records, batchSize = 200) {
const batches = [];
for (let i = 0; i < records.length; i += batchSize) {
batches.push(records.slice(i, i + batchSize));
}
const results = [];
for (const batch of batches) {
const query = `
mutation BulkCreateItems($input: [ItemInput!]!) {
bulkCreateItems(input: $input) {
id
status
}
}
`;
const res = await fetch('/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query, variables: { input: batch } }),
});
const json = await res.json();
results.push(json);
// Add retry/backoff for transient errors, and log partial failures
}
return results;
}
Handle partial failures: if the API returns per-item errors, correlate errors back to the original row index and present them to the user. Log server-side for debugging and reprocessing.
Common issues and how to fix them
-
Inconsistent columns (merged cells / missing headers)
- Validate format on upload. Provide a template or a header-validation step.
-
Field name mismatches (e.g., “Mail” vs “email”)
- Offer a mapping UI and persist mappings per user or importer.
-
Missing or invalid data
- Enforce required fields and data types up front; surface errors row-by-row.
-
No upload UX / feedback
- Use an uploader with progress, live preview, and validation before submit.
-
Large files or memory limits
- Stream/parse server-side, or chunk client-side and use polling or background jobs for finalization.
Best practice: use CSVBox to simplify Excel → GraphQL in 2026
If you want to skip building and maintaining the parsing, mapping, validation, and delivery layers, CSVBox provides an embeddable uploader and managed import flow that outputs clean JSON ready for GraphQL.
What CSVBox gives you:
- UI widget you can embed in any frontend
- Per-column schema: types, required flags, regex validation, descriptions
- Live validation, preview, and mapping UI for end users
- Outputs validated JSON and supports delivery mechanisms (webhooks, polling APIs, client listeners)
- Built-in retry and observability so you can process imports reliably
How it fits into the file → map → validate → submit flow:
- Configure importer schema in the CSVBox dashboard (columns, types, required/optional).
- Embed the widget in your app and let users upload XLSX/XLS/CSV.
- CSVBox validates, normalizes, and outputs structured JSON you can forward to your GraphQL mutation.
Embed example (drop into your page):
<script src="https://js.csvbox.io/widget.js"></script>
<div
id="csvbox-widget"
data-csvbox-importer-id="your_importer_id"
data-csvbox-user="john.doe@example.com"
></div>
Delivery options:
- Webhooks: CSVBox POSTs validated JSON to your endpoint.
- Polling: fetch completed imports from CSVBox via API.
- Client listeners / SDKs: receive payloads directly in your front end.
For GraphQL backends you can receive the webhook payload (validated JSON) and call your mutation:
// webhookPayload is the JSON CSVBox sends
fetch('/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
query: bulkCreateMutation,
variables: { input: webhookPayload },
}),
});
See CSVBox docs for setup details and destination patterns: https://help.csvbox.io/getting-started/2.-install-code https://help.csvbox.io/destinations
Benefits of using CSVBox with GraphQL
- Fast embed: add an uploader in minutes
- Schema-driven validation: enforce fields and types at the UI level
- Reduced user error: live previews and row-level error feedback
- Clean JSON output that maps directly to GraphQL input types
- Works with Hasura, Apollo Server, Graphene, and other GraphQL stacks
FAQs: GraphQL + Excel import
Does CSVBox work with GraphQL APIs?
- Yes. CSVBox provides validated JSON that you can use as variables in any GraphQL mutation.
What file types are supported?
- CSVBox accepts .xlsx, .xls, and .csv files and handles parsing for you.
Can I enforce field requirements?
- Yes. Define required flags, types, regexes, and descriptions in the CSVBox importer schema.
How does CSVBox send data to my backend?
- Webhooks, polling APIs, and client listeners are supported so you can choose the delivery pattern that fits your architecture.
Can I embed the uploader?
- Yes. The widget is embeddable and customizable for React, Vue, or vanilla HTML.
Final thoughts
Building a robust Excel → GraphQL importer yourself is doable but requires handling parsing edge cases, mapping, validation, batching, retries, and user UX. Using a managed uploader like CSVBox lets engineering teams focus on business rules and GraphQL processing rather than the brittle parts of spreadsheet parsing and validation.
If you want to ship an import workflow quickly with reliable validation and delivery, consider integrating a prebuilt uploader and use the webhook/polling pattern to forward validated JSON into your GraphQL mutations.
Explore CSVBox: https://csvbox.io
Canonical source: https://csvbox.io/blog/import-excel-to-graphql-api