Response Formats
Overview
SDAC does not use one universal response envelope across every endpoint. Consumers should expect four response styles depending on the surface they are calling.
1. Widget And Gateway JSON Endpoints
Most widget-facing /api/ingestion/sdac/... endpoints and source-backed
runtime /sdac/... endpoints return endpoint-specific JSON objects rather than
a shared { success, data } wrapper. APIM may publish selected runtime paths
for server-to-server callers.
| Endpoint Family | Typical Shape |
|---|---|
| Upload | jobId, status, stage, message, and eventually reportId/report_id |
| Validation | reportId, districtName, issues, summary |
| Report info | reportId, districtName, quarter, totals |
| Feedback | feedbackSk, success or aggregated stats |
2. Streaming Chat Responses
POST /api/ingestion/sdac/chat from the widget origin, or direct runtime
POST /sdac/chat, returns a Server-Sent Events stream.
Common event sequence:
metadata- zero or more
tool-start,tool-result,warning, anddelta usagedone
Use the Chat API page for event payload details.
3. Widget and Mastra Upload Responses
Browser widgets call POST /api/mastra/sdac/upload; the widget server forwards
to Mastra POST /sdac/upload. Both return JSON for programmatic callers.
Uploads usually start as a durable job 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"
}
The caller then polls /api/mastra/sdac/uploads/{jobId}/status from the widget
origin, or /sdac/uploads/{jobId}/status from the Mastra runtime origin, until
reportId appears. Report-analysis progress is available at
/api/mastra/sdac/report-analysis/{reportId}/status on the widget origin.
4. Upstream Passthrough Responses
The district cost proxy routes do not normalize upstream source-system shapes.
| Route | Possible Success Shapes |
|---|---|
GET /sdac/costs | bare array, { "sdac_costs": [...] }, or { "costs": [...] } |
GET /sdac/costs/{cost_id} | bare object or { "sdac_cost": { ... } } |
Common HTTP Status Meanings
| Status | Meaning |
|---|---|
400 | Invalid request body, invalid path or query value, or unsupported upload format |
401 | Missing or expired bearer token on the gateway surface |
403 | Gateway token accepted but the subscription key or scope is not allowed |
404 | Resource not found for routes that use normal HTTP not-found semantics |
422 | FastAPI validation error on ingestion-side JSON contracts |
500 | Unexpected processing failure |
502 | Widget proxy could not reach or complete the upstream ingestion request |
503 | Required upstream configuration is missing |
Route-Specific Exceptions
GET /sdac/reports/{report_id} is the main exception to normal HTTP error semantics. The ingestion implementation currently returns HTTP 200 for:
- a successful status lookup
- a missing report, signaled by
"status": "not_found" - a backend lookup failure, signaled by
"status": "error"
Inspect the response body status field for that route instead of relying on the HTTP code alone.