District Sync API
Overview
This ingestion-side route loads district cost data from the upstream source system, maps it into SDAC report structure, and returns the resulting report_id.
Direct ingestion path:
POST /sdac/sync
Widget same-origin path:
POST /api/ingestion/sdac/sync
This route is also used internally during Session Bootstrap to resolve the latest report for a district.
Authentication and Access Model
This ingestion route does not perform APIM bearer-token or subscription-key validation itself.
- Browser clients should use the widget same-origin proxy at
/api/ingestion/sdac/sync. - Direct
/sdac/syncaccess should stay behind private deployment controls or reverse-proxy authentication. - Do not expose this route directly to untrusted browser clients.
Request
| Attribute | Value |
|---|---|
| Endpoint | POST /sdac/sync |
| Content-Type | application/json |
| Response | JSON |
Request Body
{
"district_id": "12345",
"year": 2026,
"quarter": 1,
"allow_fallback": false,
"force": false
}
| Field | Type | Required | Description |
|---|---|---|---|
district_id | string | Yes | District identifier used by the source system |
year | integer | No | Reporting year. Defaults to the current UTC year |
quarter | integer | No | Quarter 1 through 4. Defaults to the current UTC quarter |
allow_fallback | boolean | No | Allows returning a different available quarter when the requested period has no data. Defaults to false |
force | boolean | No | Force a fresh sync even if a recent report already exists |
Success Response
{
"report_id": "8201EDC2-2EDE-4CA1-AF44-D0F5AA185CDB",
"status": "success",
"record_count": 21,
"synced": true,
"district_name": "Maplewood Richmond Heights",
"quarter": "Q1",
"year": 2026,
"fallback": false,
"requested_quarter": "Q1",
"requested_year": 2026,
"available_quarters": []
}
| Field | Description |
|---|---|
report_id | SDAC report identifier when a report was resolved or created |
status | Sync outcome such as success, duplicate, or empty |
record_count | Number of roster rows included in the resolved report |
synced | true when the service performed a new sync, false when it reused existing data |
district_name | Resolved district display name when available |
quarter | Quarter used for the resolved report |
year | Year used for the resolved report |
fallback | true when the service had to use a different available quarter than the one requested |
requested_quarter | Quarter originally requested by the client |
requested_year | Year originally requested by the client |
available_quarters | Diagnostic list of recent quarters with data when fallback logic was evaluated |
Empty Response
{
"report_id": null,
"status": "empty",
"record_count": 0,
"synced": false,
"fallback": false,
"requested_quarter": "Q1",
"requested_year": 2026,
"available_quarters": []
}
Error Cases
| Status | Description |
|---|---|
| 4xx | Upstream source-system request failed and was passed through |
| 500 | Sync failed locally or server-side configuration was incomplete |
Example local failure:
{
"error": "THERAPYLOG_API_URL is required.",
"synced": false
}
Side Effects
- When recent synced data already exists and
forceisfalse, the service can return the existingreport_idwithout creating a new report. - When fresh data is needed, the service fetches district cost data from the upstream source system, maps it into SDAC report structure, and writes or reuses a
THERAPYLOG_SYNCreport in the ingestion store. - If
allow_fallback=trueand the requested quarter has no usable data, the service can probe adjacent available quarters and returnfallback: truewith the actual period used.
Operational Notes
- If
forceis not set, the service may return an existing recent report instead of creating a new one. - Keep
allow_fallback=falsefor page-context loads. Use fallback only after a user explicitly chooses another available quarter. - Use Report Status API or the gateway-facing Report Info API after sync, depending on whether you need ingestion-state detail or review metadata.