Permissions.simulation in the reference webapp.
What you’ll build
- A file picker (
.xls/.xlsx). - Client-side column validation + workbook normalisation.
- An upload action (indeterminate loading state).
- A success toast + redirect, or a row-level error screen.
File formats
XLS / XLSX only. The reference FE uses thexlsx library and does
not accept CSV.
Prerequisites
- An authenticated user with
Permissions.simulation. X-Preferred-Partner-Idset.- The partner’s product / access tier — drives
event_type(see below).
Deriving event_type
The reference FE does not use Permissions.prisma / Permissions.fdlive.
It derives event_type dynamically:
prismawhenhasPartialServiceAccessTier()is true (partner productPRISMAorFD_FULL_SERVICE) or the page was reached from Wave (location.state?.from === 'wave')- otherwise
fdlive
The call chain
On upload:| Method | URL | Host | Notes |
|---|---|---|---|
| POST | events/bulk_upload?event_type=prisma|fdlive | CR API | multipart/form-data, field name file. Manually attach Authorization and X-Preferred-Partner-Id (the FE uses a direct axios call, not the shared instance). |
Pre-upload validation and normalisation
Before sending, the reference FE:- Validates required columns — the required set differs between
prismaandfdlive. - Normalises the workbook (
delocalizeSheetAndHeaders,formatSheetFromArrays) — so the uploaded file is not always sent verbatim; headers and localised values are transformed first.
Template download
EU / US and language are chosen per partner. This is not
/downloads/sales_template.xlsx.)
Response handling
The HTTP status is200 for both full success and partial failure — you
must inspect the body. Two shapes:
Row-level errors — [400, errs] with HTTP 200:
Object.keys(errorObj) — i.e.
it expects each error object shaped like { "ROW_3_INVALID_DATE": ... },
not { "errCode": "ROW_3_INVALID_DATE" }.
Top-level error — in the .catch branch:
/ after ~2s.
Reference implementation
Gotchas
XLS/XLSX only — no CSV
XLS/XLSX only — no CSV
The reference FE rejects CSV. Accept
.xls / .xlsx.CR API host, not main API
CR API host, not main API
Sending this to the main API returns 404.
Manually attach auth headers
Manually attach auth headers
The FE uses a direct axios call (no
transformRequest), so it adds
Authorization + X-Preferred-Partner-Id by hand. Replicate or 401.Error parsing uses Object.keys, not errCode
Error parsing uses Object.keys, not errCode
The
[400, errs] shape carries { "ROW_x_...": ... } objects — read
keys, not an errCode field.Normalise the workbook before upload
Normalise the workbook before upload
The FE transforms headers/values and validates required columns
(which differ for prisma vs fdlive) before sending. Don’t send the
user’s file verbatim.
`Permissions.simulation` gates the route
`Permissions.simulation` gates the route
Not prisma/fdlive permission enums.
Related
- Event editor — same host, single-event flow.
- Simulation — same host, creates a single event.
- File uploads cookbook.