> ## Documentation Index
> Fetch the complete documentation index at: https://docs.go.aiinsurance.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Download Entity Export Run

> Downloads the file a **succeeded** export run produced — the file half of
**`POST /entities/{entityType}/export-runs`**.

By default (`format=csv`, or no `format` at all) the response is the CSV
itself (`text/csv; charset=utf-8`, served as an attachment), streamed from
storage: the first row is the header (each requested column's `label`, in
the requested order), followed by one row per exported record. A zero-row
export downloads as a header-only CSV.

**`format=xlsx`** downloads the same export as an Excel workbook
(`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`): one
worksheet carrying exactly the CSV's cells — the conversion changes the
file format, never the values. The workbook is produced server-side on the
first request and cached, so repeat downloads are cheap. An export whose
rows would not fit on one Excel worksheet (1,048,576 rows including the
header) is refused with a `409` — the CSV download still works and carries
every row.

**Only a `succeeded` run downloads.** Every other status is a `404`:
`queued` and `running` have no file yet, `failed` never produced one, and
`expired` means the file passed its retention horizon and was deleted. Poll
**`GET .../export-runs/{runId}`** to learn which — the poll stays readable
for every status — and start a new export when the run failed or expired.
The file stays downloadable until the run's `expiresAt`, and can be
downloaded any number of times until then.

**Required permission:** `company.{entity}:list` — the exact key varies by
type (Policy uses `company.policy:export`), derived from the path's
`{entityType}`. See
[Permissions](/api-reference/entities/overview#permissions).




## OpenAPI

````yaml /openapi/generated-external-api.yaml get /api/v1/companies/{companyId}/entities/{entityType}/export-runs/{runId}/download
openapi: 3.0.3
info:
  title: AI Insurance External API
  description: External API for AI Insurance platform
  version: 1.0.0
  contact:
    email: support@aiinsurance.io
servers:
  - url: https://go.aiinsurance.io
    description: Production
security:
  - ApiKeyAuth: []
paths:
  /api/v1/companies/{companyId}/entities/{entityType}/export-runs/{runId}/download:
    get:
      tags:
        - Entities
      summary: Download Entity Export Run
      description: >
        Downloads the file a **succeeded** export run produced — the file half
        of

        **`POST /entities/{entityType}/export-runs`**.


        By default (`format=csv`, or no `format` at all) the response is the CSV

        itself (`text/csv; charset=utf-8`, served as an attachment), streamed
        from

        storage: the first row is the header (each requested column's `label`,
        in

        the requested order), followed by one row per exported record. A
        zero-row

        export downloads as a header-only CSV.


        **`format=xlsx`** downloads the same export as an Excel workbook

        (`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`):
        one

        worksheet carrying exactly the CSV's cells — the conversion changes the

        file format, never the values. The workbook is produced server-side on
        the

        first request and cached, so repeat downloads are cheap. An export whose

        rows would not fit on one Excel worksheet (1,048,576 rows including the

        header) is refused with a `409` — the CSV download still works and
        carries

        every row.


        **Only a `succeeded` run downloads.** Every other status is a `404`:

        `queued` and `running` have no file yet, `failed` never produced one,
        and

        `expired` means the file passed its retention horizon and was deleted.
        Poll

        **`GET .../export-runs/{runId}`** to learn which — the poll stays
        readable

        for every status — and start a new export when the run failed or
        expired.

        The file stays downloadable until the run's `expiresAt`, and can be

        downloaded any number of times until then.


        **Required permission:** `company.{entity}:list` — the exact key varies
        by

        type (Policy uses `company.policy:export`), derived from the path's

        `{entityType}`. See

        [Permissions](/api-reference/entities/overview#permissions).
      operationId: downloadEntityExportRun
      parameters:
        - $ref: '#/components/parameters/companyId'
        - $ref: '#/components/parameters/exportEntityType'
        - name: runId
          in: path
          required: true
          schema:
            type: string
            format: uuid
          description: >
            The run identifier returned by **`POST

            /entities/{entityType}/export-runs`**. Runs are scoped to their
            company

            AND their entity type: a run id belonging to another company, or
            started

            under a different entity type, returns `404`, exactly as an id that

            exists nowhere does.
        - name: format
          in: query
          required: false
          schema:
            type: string
            enum:
              - csv
              - xlsx
            default: csv
          description: >
            The file format to download: `csv` (the default) for the export's
            CSV,

            `xlsx` for its Excel workbook rendition. Any other value is a `400`
            —

            never silently defaulted, because that would serve a different file

            than the one asked for.
      responses:
        '200':
          description: |
            The exported file, streamed as an attachment named
            `{entityType}-export-{runId}.{format}`.
          content:
            text/csv:
              schema:
                type: string
              examples:
                csv:
                  summary: The parked CSV file
                  value: |
                    Exposure Name,Exposure Type
                    Acme Corp HQ,company
                    Beta Warehouse,company
            application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
              schema:
                type: string
                format: binary
              examples:
                xlsx:
                  summary: The Excel workbook rendition (`format=xlsx`)
                  value: (binary XLSX bytes)
        '400':
          description: |
            Bad Request - the entity type is not exportable, the run id path
            parameter is missing or is not a UUID, or `format` is neither `csv`
            nor `xlsx`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                invalidRunId:
                  summary: Missing or malformed run id
                  value:
                    error:
                      code: INVALID_RUN_ID
                      message: A run id path parameter is required, and must be a UUID.
                invalidFormat:
                  summary: Unknown download format
                  value:
                    error:
                      code: INVALID_EXPORT_FORMAT
                      message: >-
                        The format query parameter must be `csv` or `xlsx` when
                        present.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: >
            Not Found — no DOWNLOADABLE file exists here. Either no run with
            this id

            exists for this company under this entity type (a run id belonging
            to a

            different company, or started under a different entity type, is
            reported

            the same way), or the run exists but is not `succeeded`: still
            `queued`

            or `running`, `failed`, or `expired` after its retention horizon.
            Poll

            the run's status endpoint to learn which.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                notFound:
                  summary: Unknown run id for this company and entity type
                  value:
                    error:
                      code: NotFound
                      message: >-
                        Export run 7c9e6679-7425-40de-944b-e07fc1f90ae7 not
                        found.
                notDownloadable:
                  summary: The run exists but has no downloadable artifact
                  value:
                    error:
                      code: NotFound
                      message: >-
                        Export run 7c9e6679-7425-40de-944b-e07fc1f90ae7 has no
                        downloadable artifact (status: expired).
        '409':
          description: >
            Conflict — `format=xlsx` was requested, but the run's rows (plus the

            header row) exceed Excel's 1,048,576-row worksheet ceiling, so no
            XLSX

            rendition can be produced. The CSV download remains available and

            carries every row.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                tooLarge:
                  summary: The export does not fit on one Excel worksheet
                  value:
                    error:
                      code: ExportTooLargeForXlsx
                      message: >-
                        Export run 7c9e6679-7425-40de-944b-e07fc1f90ae7 has
                        2000000 data rows; with the header row that exceeds
                        Excel's 1048576-row worksheet ceiling, so no XLSX
                        rendition can be produced. The CSV download remains
                        available and carries every row.
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
        - ApiKeyAuth: []
components:
  parameters:
    companyId:
      name: companyId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: Company identifier
    exportEntityType:
      name: entityType
      in: path
      required: true
      schema:
        type: string
        enum:
          - event
          - exposure
          - quote
          - submission
          - person
          - organization
          - policy
      description: >
        Field Model V1 EXPORTABLE entity type (lowercase kebab-case URL slug):
        the six

        CRUD entity types plus `policy`. Unlike the CRUD entity routes, `policy`
        IS

        valid here — a Policy export reads the segment in effect on the `asOf`
        date

        (defaulting to today).
  schemas:
    ErrorResponse:
      type: object
      description: Standard error response for all external API endpoints
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: Machine-readable error code
              example: VALIDATION_ERROR
            message:
              type: string
              description: Human-readable error message
              example: 'submissionId: Required field is missing'
            userMessages:
              type: array
              description: >-
                Clean, verbatim-displayable messages — one entry per failure,
                free of error-code tags, field paths, and internal noise.
                Suitable for showing to end users as-is.
              items:
                type: string
              example:
                - Exposures of type 'company' require an address
            details:
              type: array
              description: Additional details for validation errors (field-level errors)
              items:
                type: object
                properties:
                  field:
                    type: string
                    description: The field that caused the error
                    example: submissionId
                  message:
                    type: string
                    description: Description of the field error
                    example: Required field is missing
  responses:
    Unauthorized:
      description: Unauthorized - Invalid or missing API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            missingApiKey:
              summary: Missing API key
              value:
                error:
                  code: AuthenticationError
                  message: API key authentication required
                  userMessages:
                    - API key authentication required
            invalidApiKey:
              summary: >-
                Invalid API key (e.g. unknown key, or a Bearer token used
                instead of an API key)
              value:
                error:
                  code: AuthenticationError
                  message: Invalid API key
                  userMessages:
                    - Invalid API key
    Forbidden:
      description: Forbidden - Insufficient permissions
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            insufficientPermissions:
              summary: Insufficient permissions
              value:
                error:
                  code: AuthorizationError
                  message: User is not authorized to perform the requested action
                  userMessages:
                    - User is not authorized to perform the requested action
            companyMismatch:
              summary: A valid API key naming another company in the URL
              value:
                error:
                  code: AuthorizationError
                  message: API key is not scoped to the requested company
                  userMessages:
                    - API key is not scoped to the requested company
    InternalServerError:
      description: Internal Server Error - Unexpected error occurred
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            internalError:
              summary: Unexpected server error
              value:
                error:
                  code: UncaughtActionError
                  message: Uncaught error occurred in <actionName>
                  userMessages:
                    - An unexpected error occurred. Please try again later.
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: Authorization
      description: >-
        API key authentication. Send your raw API key as the `Authorization`
        header value with NO scheme prefix — `Authorization: YOUR-API-KEY`. Do
        NOT prefix it with `Bearer ` or `ApiKey `, and do not use an `X-API-Key`
        header; those are not accepted.
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        User-principal OAuth 2.0 Bearer authentication. Send a user-scoped Auth0
        access token (audience = the app API audience) as `Authorization: Bearer
        <jwt>`. The request resolves to the user's identity and is authorized by
        their Role on the `{companyId}` in the path — the same role-based
        permissions the web app enforces. This is the path the MCP connector
        uses to act on a user's behalf; endpoints that accept it list both
        `BearerAuth` and `ApiKeyAuth`.

````