Skip to main content

Widget Upload API

Overview

The widget sends SDAC workbook uploads to its same-origin backend at /api/mastra/sdac/upload. The backend proxies to Mastra, and Mastra submits the workbook to the ingestion worker internally.

Do not point browser clients at the ingestion worker. The ingestion worker is an internal parser surface; Mastra owns upload status, report analysis startup, and the durable job record.

Authentication and Access Model

The widget backend should be protected by the normal widget/APIM authentication controls. It forwards calls to Mastra server-to-server.

  • Browser clients call /api/mastra/sdac/upload.
  • Mastra calls the ingestion worker with service-to-service credentials.
  • The ingestion worker should not be exposed directly to untrusted browser clients.

Request

Use multipart/form-data.

AttributeValue
EndpointPOST /api/mastra/sdac/upload
ResponseJSON
FieldTypeRequiredDescription
filefileYesExcel workbook in .xlsx or .xls format
user_emailstringYesEmail of the uploader
user_namestringYesDisplay name of the uploader
districtstringYesDistrict or organization label
force_reingestbooleanNoForce a new ingest even if the file hash already exists

Response Format

The route renders HTML only when the request explicitly prefers text/html. Browser fetch() calls and widget integrations receive JSON by default.

Accepted Response

{
"status": "processing",
"jobId": "11111111-1111-4111-8111-111111111111",
"stage": "processing_file",
"message": "The ingestion worker accepted the file and is parsing it now.",
"statusUrl": "/sdac/uploads/11111111-1111-4111-8111-111111111111/status",
"largeFile": false,
"stalled": false
}

statusUrl is Mastra-relative. Browser/widget clients should not fetch it directly; poll /api/mastra/sdac/uploads/{jobId}/status on the widget origin. Once the status response includes reportId, the widget polls /api/mastra/sdac/report-analysis/{reportId}/status until report analysis completes.

Duplicate Response

{
"status": "duplicate",
"report_id": "8201EDC2-2EDE-4CA1-AF44-D0F5AA185CDB",
"record_count": 21,
"message": "This file has already been uploaded. You can use the existing report or re-ingest under a new ID.",
"can_reingest": true,
"existing_report": {
"district": "Maplewood Richmond Heights",
"quarter": "Q3",
"year": 2025,
"processed_at": "2026-03-29T18:42:11.000Z"
}
}

Error Response

{
"status": "error",
"report_id": "8201EDC2-2EDE-4CA1-AF44-D0F5AA185CDB",
"record_count": 0,
"message": "Processing failed: Validation failed"
}

HTTP Status Codes

StatusDescription
200Immediate duplicate or completed upload response
202Upload accepted; poll the returned job status URL
400Missing file, invalid file extension, invalid workbook structure, or missing workbook data
502Mastra could not submit to or refresh the ingestion worker
500Unexpected Mastra upload failure

Side Effects

  • Successful uploads create SDAC.ingestion_UploadJobs, insert parsed report rows through the ingestion worker, then start Mastra report analysis.
  • Duplicate uploads return the existing report reference and do not create a new report unless force_reingest is set.
  • Failed uploads persist error state on the upload job when a job was created.