# Bulk Data files and submitted revisions

Source: https://govform.com/resources/documentation/article/33-14-api-bulk-data-files
Topic: Govform API & MCP

## Bulk Data files and submitted revisions

A Bulk Data answer is compact metadata, not an array of rows or file contents. The validated CSV includes the respondent's corrections. Their first submitted CSV is their original submitted evidence; the untouched upload is a separate retained source and may still contain mistakes.

For Cloud accounts, each successful submitted-data Bulk Data download uses 25 API units, regardless of page-size parameters. Government Cloud accounts are exempt from these quotas.

### Processing scale and evidence

Bulk Data validates up to **five million data cells** across up to **200 configured columns**, for example 500,000 rows with 10 columns. CSV and selected XLSX worksheet rows are processed as streams in background jobs, with progress, previews and error reports. Optional browser correction operates in batches of up to 1,000 rows before explicit confirmation.

The source upload uses the file component’s size and security settings: 10 MB default, up to 20 GB where configured, subject to store and processing limits. CDR defaults to 50 MB on single-file components; current external-store Govform AV transfers support up to 5 GB. [Compare input-file limits and scanning choices](<https://govform.com/resources/documentation/article/23-09-component-file>).

Streaming download and Upload files paths transfer a retained artifact; they do not re-ingest it or consume the Base64 API-body allowance. Keep the original source, confirmed CSV and submitted revision selectors distinct.

### Download a Bulk Data file

`GET /api/submitted-data/{libraryId}/{serviceId}/{submissionId}/bulk/{fieldId}/{artifact}?version=first-submitted`

Use the **Bulk Data field ID**, not the linked upload field ID. This endpoint requires a completed submission and the existing **Fetch submitted data** API-key permission, using `GovformsApiKey` or `GovformsApiHmac` authentication. It streams bytes without Base64. Existing tenant and Response history scope boundaries apply.

| Selector | Values |
| --- | --- |
| `artifact` (path) | `current`: validated CSV; `source`: untouched upload associated with the selected evidence; `errors`: retained validation-errors CSV, when available. |
| `version` (query) | Omit or use `current` for current confirmed data; `first-submitted` for submitted revision 1; a positive integer for a specific submitted revision. |
| `iteration` (query) | Zero-based repeat row; required for repeating Bulk Data, omitted otherwise. |

Submitted revision numbers are Response history revisions, **not internal dataset edit numbers**. First submitted means revision 1 even if the field was added later. Historical files require retained Response history; some services do not retain it and capture can finish after submission. Missing history or files never fall back to current data. Retention still controls availability. Historical selection can retrieve evidence from a field removed from the current service definition.

Downloads return the selected file's content type and attachment filename, and content length where available. There is no Base64-size ceiling on this streaming route; clients should stream it and account for network/provider timeouts. `400` indicates malformed selectors, `403` insufficient API permission, `404` unavailable submission/evidence/file, and `409` evidence that no longer matches its confirmed dataset.

### Send Bulk Data in an API action

```liquid
{
  "csvBase64": "{{ bulkDataField | file_to_base64 }}",
  "firstSubmittedCsvBase64": "{{ bulkDataField | file_to_base64: version: "first-submitted", artifact: "current" }}"
}
```

Optional named literal arguments `version` and `artifact` use the same meanings as the download API. The filter accepts `current` or `source` artifacts; `errors` is download-only. For a repeating component, precede named arguments with the existing positional selectors: `{{ bulkDataField | file_to_base64: 0, 2, version: 1 }}` selects repeat row 2 in submitted revision 1. Selectors must be literals, not Liquid variables or chained filters.

Existing ordinary-file filter calls are unchanged. Selecting the linked ordinary upload field still returns the untouched upload. `files_to_base64` does not accept Bulk Data. Both filters work only in API action bodies; User view supplies mock content. Test actual files in QA.

The combined raw-file allowance is **25 MiB per API action**, including repeated occurrences. Base64 adds approximately one third: 25 MiB becomes about 33.3 MiB before JSON overhead. Receiving systems may allow less. The **10 MiB API limit is for responses**, not outgoing request bodies. Missing or oversized content fails before sending. For larger datasets use streamed downloads or Upload files.

### Deliver files directly to a file store

Use **Page actions → Upload files** (previously SharePoint upload/Site upload). Select a configured SharePoint, S3, Google Cloud Storage, Azure Blob Storage or Govform storage destination, select the Bulk Data component, and choose its evidence version and file. Defaults are current confirmed data and validated CSV. Enter the destination filename without an extension; Govform adds `.csv` for validated data or the untouched upload's original extension. Each upload row can select a different revision; use distinct filenames when retaining several exports.

Run after the respondent confirms their data. Existing action triggers and workflows apply; historical selections must wait until their Response history revision exists. QA and Production use their configured connections. Large file transfers stream through the existing storage providers and are not subject to the Base64 limit, although provider and execution limits still apply.

This delivers one file. Creating a SharePoint list item for each CSV row requires an external row-processing integration; the ordinary list-item action is not a bulk importer.
