Skip to main content

Structured Payload Ingest API

Overview

This ingestion-side route accepts parsed SDAC roster data as JSON and runs it through the same registration and deduplication flow used for workbook uploads.

Direct ingestion path:

  • POST /sdac/ingest

Widget same-origin path:

  • POST /api/ingestion/sdac/ingest

Use this route when your integration already has normalized SDAC data and does not need to upload an Excel workbook.

Authentication and Access Model

This ingestion route does not perform APIM bearer-token or subscription-key validation itself.

  • Browser clients should call the widget same-origin proxy at /api/ingestion/sdac/ingest.
  • Direct /sdac/ingest access should stay behind private networking, host-application controls, or reverse-proxy authentication.
  • Do not expose the ingestion route directly to untrusted browser clients.

Request

AttributeValue
EndpointPOST /sdac/ingest
Content-Typeapplication/json
ResponseJSON

Request Body

{
"user_email": "auditor@state.gov",
"user_name": "Alex Auditor",
"district": "Maplewood Richmond Heights",
"metadata": {
"quarter": "Q1",
"year": 2026
},
"main_roster": [
{
"first_name": "Jane",
"last_name": "Doe",
"job_title": "Speech Pathologist",
"source_code": "1",
"function_code": "2100",
"gross_salary": 75000,
"fringe": 18750
}
],
"replacements": [],
"source_name": "district-export.json",
"force_reingest": false
}
FieldTypeRequiredDescription
user_emailstringYesEmail of the submitting user
user_namestringYesDisplay name of the submitting user
districtstringYesDistrict or organization label stored with the report
metadataobjectYesReport-level metadata such as quarter and year
main_rosterarrayYesMain personnel rows
replacementsarrayNoReplacement rows
source_namestringNoSource label stored for traceability
force_reingestbooleanNoBypass duplicate-payload detection and create a new report

Success Response

{
"status": "success",
"reportId": "8201EDC2-2EDE-4CA1-AF44-D0F5AA185CDB",
"message": "Successfully processed 21 records and archived to https://storage.example.com/sdac-archive/...",
"recordCount": 21,
"canReingest": false,
"existingReport": null
}

Duplicate Response

{
"status": "duplicate",
"reportId": "8201EDC2-2EDE-4CA1-AF44-D0F5AA185CDB",
"message": "This content has already been ingested. Using existing report.",
"recordCount": 0,
"canReingest": true,
"existingReport": {
"district": "Maplewood Richmond Heights",
"quarter": "Q1",
"year": 2026,
"processed_at": "2026-03-30T09:15:00.000Z"
}
}

Error Response

{
"status": "error",
"reportId": null,
"message": "Processing failed: ...",
"recordCount": 0,
"canReingest": false,
"existingReport": null
}

Validation failures caused by missing required fields return FastAPI validation errors with status 422.

Error Cases

StatusDescription
200Report created successfully or duplicate payload resolved to an existing report
422FastAPI validation failed because required JSON fields were missing or typed incorrectly
500Payload processing failed after the request was accepted

Side Effects

  • The service hashes the submitted payload for duplicate detection before it writes any new report.
  • Successful requests stage a JSON payload artifact, insert personnel rows into the ingestion tables, and archive the payload plus metadata.
  • Duplicate payloads return the existing report reference and do not create a new report unless force_reingest is set.

Operational Notes

  • This route is ingestion-side only. It is not part of the gateway-facing /ai/... API surface.
  • The service hashes the structured payload for duplicate detection in the same way workbook uploads hash files.
  • Use Report Status API after ingest if your UI needs ingestion-state confirmation.