> ## 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.

# Start Entity Export Run

> Starts an **export run**: a background job that produces the FULL filtered
result set of one entity type as a **CSV file**, however large it is. Returns
immediately with a `runId` — poll
**`GET /entities/{entityType}/export-runs/{runId}`** until the run succeeds,
then fetch the file from
**`GET /entities/{entityType}/export-runs/{runId}/download`**.

A run streams rows into a stored CSV in the background and lets you download
the finished file without holding the full result set in request memory.

### The request body is OPTIONAL

The body is the export request:

- **`fields`** — the export columns, in CSV column order. **Omit it (or send
  no body at all) to export the type's full default column set**: the system
  `id` / `createdAt` / `updatedAt` columns followed by every configured
  column of the type's export surface.
- **`filters`** / **`filterText`** — the same generic filters the
  [List Entities](/api-reference/entities/list-entities) endpoint accepts.
- **`sortBy`** / **`sortDirection`** — row order.
- **`asOf`** — point-in-time lens (`YYYY-MM-DD`): for Policy it resolves each
  policy to the segment in effect on that date, for Event it bounds the
  financial export columns.

A body that arrives and cannot be read as JSON is a `400`
(`UNREADABLE_REQUEST_BODY`) — it is never treated as an omitted body, because
that would export different columns and rows than the ones asked for.

The run snapshots the request AND the company's current configuration version
when it starts, so what a queued export produces cannot drift: a
configuration import landing mid-run does not change the file.

### Duplicate starts collapse onto the run already in flight

If a run is already in flight (`queued` or `running`) producing this **exact
export** — same request, same configuration version — this endpoint does not
start a second one: it returns `200` with that run's id and
`outcome: "duplicate"`. That is a normal, successful answer, not an error.
Pass **`?force=true`** to start a new run anyway. A run that already
**finished** is never deduplicated onto — re-asking for the same export is
how you refresh the file.

### At most 3 runs in flight per company

A company may have **3** export runs in flight at once. A 4th distinct
request is refused with a `429` whose body carries `inFlightRunIds` — poll
those instead of retrying blind. `?force=true` does **not** lift this limit.

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




## OpenAPI

````yaml /openapi/generated-external-api.yaml post /api/v1/companies/{companyId}/entities/{entityType}/export-runs
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:
    post:
      tags:
        - Entities
      summary: Start Entity Export Run
      description: >
        Starts an **export run**: a background job that produces the FULL
        filtered

        result set of one entity type as a **CSV file**, however large it is.
        Returns

        immediately with a `runId` — poll

        **`GET /entities/{entityType}/export-runs/{runId}`** until the run
        succeeds,

        then fetch the file from

        **`GET /entities/{entityType}/export-runs/{runId}/download`**.


        A run streams rows into a stored CSV in the background and lets you
        download

        the finished file without holding the full result set in request memory.


        ### The request body is OPTIONAL


        The body is the export request:


        - **`fields`** — the export columns, in CSV column order. **Omit it (or
        send
          no body at all) to export the type's full default column set**: the system
          `id` / `createdAt` / `updatedAt` columns followed by every configured
          column of the type's export surface.
        - **`filters`** / **`filterText`** — the same generic filters the
          [List Entities](/api-reference/entities/list-entities) endpoint accepts.
        - **`sortBy`** / **`sortDirection`** — row order.

        - **`asOf`** — point-in-time lens (`YYYY-MM-DD`): for Policy it resolves
        each
          policy to the segment in effect on that date, for Event it bounds the
          financial export columns.

        A body that arrives and cannot be read as JSON is a `400`

        (`UNREADABLE_REQUEST_BODY`) — it is never treated as an omitted body,
        because

        that would export different columns and rows than the ones asked for.


        The run snapshots the request AND the company's current configuration
        version

        when it starts, so what a queued export produces cannot drift: a

        configuration import landing mid-run does not change the file.


        ### Duplicate starts collapse onto the run already in flight


        If a run is already in flight (`queued` or `running`) producing this
        **exact

        export** — same request, same configuration version — this endpoint does
        not

        start a second one: it returns `200` with that run's id and

        `outcome: "duplicate"`. That is a normal, successful answer, not an
        error.

        Pass **`?force=true`** to start a new run anyway. A run that already

        **finished** is never deduplicated onto — re-asking for the same export
        is

        how you refresh the file.


        ### At most 3 runs in flight per company


        A company may have **3** export runs in flight at once. A 4th distinct

        request is refused with a `429` whose body carries `inFlightRunIds` —
        poll

        those instead of retrying blind. `?force=true` does **not** lift this
        limit.


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

        type (Policy uses `company.policy:export`). See

        [Permissions](/api-reference/entities/overview#permissions).
      operationId: startEntityExportRun
      parameters:
        - $ref: '#/components/parameters/companyId'
        - $ref: '#/components/parameters/exportEntityType'
        - name: force
          in: query
          required: false
          schema:
            type: boolean
            default: false
          description: >
            When `true`, start a new run even if a run is already in flight
            producing

            this exact export — i.e. skip the duplicate check and always mint a
            fresh

            run. Any value other than the literal `true` (including omission) is

            treated as `false`. This does **not** raise the limit of 3 runs in
            flight

            per company.
      requestBody:
        required: false
        description: >
          OPTIONAL. The export request; omit it entirely (or send `{}`) to
          export the

          type's full default column set with no filters. A body that cannot be
          read

          as JSON is a `400`, never a silent default export.
        content:
          application/json:
            schema:
              type: object
              properties:
                fields:
                  type: array
                  description: >-
                    Explicit export columns, in CSV column order. Omit to export
                    the type's full default column set (system columns + every
                    configured column of the type's export surface).
                  items:
                    type: object
                    required:
                      - referenceId
                      - type
                      - label
                    properties:
                      referenceId:
                        type: string
                      type:
                        type: string
                        enum:
                          - field-model-v1
                          - financial
                          - system
                      label:
                        type: string
                        description: The CSV header printed for this column
                filters:
                  type: array
                  description: >
                    Filters applied to the export snapshot with AND semantics.

                    Tenant filters must use `fieldType: "declared"` and a key
                    from

                    the entity surface's `listFilters`. Explicit `systemUser`,

                    `systemDate`, and `systemId` forms remain supported.


                    Implicit field-derived forms fail at admission with HTTP
                    `400`

                    and code `implicit-filters-disabled`; no run is persisted or

                    enqueued.
                  items:
                    $ref: '#/components/schemas/FieldModelV1ListFilter'
                filterText:
                  type: string
                  description: Free-text filter over the type's search fields
                sortBy:
                  type: string
                sortDirection:
                  type: string
                  enum:
                    - asc
                    - desc
                asOf:
                  type: string
                  format: date
                  description: >-
                    Point-in-time lens (`YYYY-MM-DD`); see the endpoint
                    description.
            examples:
              explicitColumns:
                summary: Export two columns of the filtered set
                value:
                  fields:
                    - referenceId: exposureName
                      type: field-model-v1
                      label: Exposure Name
                    - referenceId: exposureType
                      type: field-model-v1
                      label: Exposure Type
                  filterText: acme
              defaultExport:
                summary: >-
                  Export the full default column set (an omitted body does the
                  same)
                value: {}
      responses:
        '200':
          description: >
            The run to poll. `outcome: "enqueued"` means a new export was
            started;

            `outcome: "duplicate"` means `runId` is a run already in flight
            producing

            this exact export and no second one was started.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExportRunStartResponse'
              examples:
                enqueued:
                  summary: A new export run was started
                  value:
                    runId: 7c9e6679-7425-40de-944b-e07fc1f90ae7
                    outcome: enqueued
                duplicate:
                  summary: A run producing this exact export was already in flight
                  value:
                    runId: 7c9e6679-7425-40de-944b-e07fc1f90ae7
                    outcome: duplicate
        '400':
          description: Bad Request - invalid entity type or request body
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                invalidEntityType:
                  summary: The path's entityType is not an exportable entity type
                  value:
                    error:
                      code: INVALID_ENTITY_TYPE
                      message: Invalid entity type. Must be a configured entity.
                unreadableRequestBody:
                  summary: >-
                    A body was sent that could not be read as JSON (wrong or
                    missing Content-Type, or invalid JSON)
                  value:
                    error:
                      code: UNREADABLE_REQUEST_BODY
                      message: >-
                        A request body was sent with Content-Type "text/plain",
                        and this endpoint reads only application/json. Send the
                        export request as an `application/json` body, or send NO
                        body at all to export the full default column set. A
                        body that cannot be read is never treated as an omitted
                        one, because that would export different columns and
                        rows than the ones asked for.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '409':
          description: >
            Conflict — this company has no stored configuration version to
            export

            against yet. Import a configuration first.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                noConfigVersion:
                  summary: The company has never imported a configuration
                  value:
                    error:
                      code: NoCompanyConfigVersion
                      message: >-
                        This company has no stored configuration version to
                        export against. Import a configuration first.
        '429':
          description: >
            Too Many Requests — this company already has 3 export runs in
            flight, so

            no run was started. The body carries `inFlightRunIds`: poll those
            runs

            and start again once one reaches a terminal status. `?force=true`
            does

            not bypass this.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExportRunsTooManyInFlightResponse'
              examples:
                tooManyInFlight:
                  summary: The per-company in-flight limit was reached
                  value:
                    error:
                      code: TooManyActiveExportRuns
                      message: >-
                        This company already has 3 export runs in flight (the
                        limit is 3). Poll the runs already in flight, or wait
                        for one to finish before starting another.
                      inFlightRunIds:
                        - 7c9e6679-7425-40de-944b-e07fc1f90ae7
                        - 1f0c9a52-2f8d-4a3e-9b7a-2c4f6d8e0a11
                        - 3b8d4f61-5a2c-4e7b-8d1f-9c0e2a4b6d83
        '500':
          $ref: '#/components/responses/InternalServerError'
        '503':
          description: >
            Service Unavailable — another start for this company was holding the

            admission lock, so this request gave up waiting for it. **Nothing
            was

            started** and no run was created. Retry in a few seconds; starting
            many

            runs for one company concurrently is what provokes this.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                admissionBusy:
                  summary: A concurrent start held the per-company admission lock
                  value:
                    error:
                      code: ExportRunAdmissionBusy
                      message: >-
                        Could not start an export: another export start for this
                        company is holding the admission lock. Nothing was
                        started. Retry in a few seconds.
      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:
    FieldModelV1ListFilter:
      description: >
        A filter accepted by FMV1 external list, version, and export endpoints.


        Tenant-field filters must use `fieldType: declared` and the `key` of a

        `listFilters` definition on the surface being queried. The definition
        supplies

        the SQL expression, result type, and permitted operators; the request
        supplies

        only its key, an exposed operator, and an operand of that operator's
        shape.


        The fixed `systemUser`, `systemDate`, and `systemId` forms remain
        explicit.

        Implicit field-derived forms such as `text`, `number`, `optionSet`, or
        `join`

        are rejected with `400` and code `implicit-filters-disabled`.
      oneOf:
        - type: object
          additionalProperties: false
          description: Apply a tenant-declared list filter.
          required:
            - fieldType
            - key
            - operator
            - value
          properties:
            fieldType:
              type: string
              enum:
                - declared
            key:
              type: string
              description: Key of the declared list filter on the queried surface.
            operator:
              type: string
              enum:
                - equals
                - notEquals
                - contains
                - doesNotContain
                - gt
                - lt
                - gtOrEqual
                - ltOrEqual
                - between
                - before
                - after
                - in
                - notIn
                - includesAny
                - includesAll
                - excludes
                - jsonContains
                - hasKey
            value:
              description: Operand validated against the resolved definition and operator.
        - type: object
          additionalProperties: false
          description: Filter by the user who created or updated the row.
          required:
            - fieldReferenceId
            - fieldType
            - operator
            - value
            - systemColumn
          properties:
            fieldReferenceId:
              type: string
            fieldType:
              type: string
              enum:
                - systemUser
            operator:
              type: string
              enum:
                - in
            value:
              type: array
              items:
                type: string
            systemColumn:
              type: string
              enum:
                - createdBy
                - updatedBy
        - type: object
          additionalProperties: false
          description: Compare the row's created or updated date.
          required:
            - fieldReferenceId
            - fieldType
            - operator
            - value
            - systemColumn
          properties:
            fieldReferenceId:
              type: string
            fieldType:
              type: string
              enum:
                - systemDate
            operator:
              type: string
              enum:
                - 'on'
                - before
                - after
            value:
              type: object
              additionalProperties: false
              required:
                - year
                - month
                - day
              properties:
                year:
                  type: integer
                month:
                  type: integer
                  minimum: 1
                  maximum: 12
                day:
                  type: integer
                  minimum: 1
                  maximum: 31
            systemColumn:
              type: string
              enum:
                - createdAt
                - updatedAt
        - type: object
          additionalProperties: false
          description: Inclusive range on the row's created or updated date.
          required:
            - fieldReferenceId
            - fieldType
            - operator
            - value
            - valueTo
            - systemColumn
          properties:
            fieldReferenceId:
              type: string
            fieldType:
              type: string
              enum:
                - systemDate
            operator:
              type: string
              enum:
                - between
            value:
              type: object
              additionalProperties: false
              required:
                - year
                - month
                - day
              properties:
                year:
                  type: integer
                month:
                  type: integer
                  minimum: 1
                  maximum: 12
                day:
                  type: integer
                  minimum: 1
                  maximum: 31
            valueTo:
              type: object
              additionalProperties: false
              required:
                - year
                - month
                - day
              properties:
                year:
                  type: integer
                month:
                  type: integer
                  minimum: 1
                  maximum: 12
                day:
                  type: integer
                  minimum: 1
                  maximum: 31
            systemColumn:
              type: string
              enum:
                - createdAt
                - updatedAt
        - type: object
          additionalProperties: false
          description: Filter by one or more entity row IDs.
          required:
            - fieldReferenceId
            - fieldType
            - operator
            - value
          properties:
            fieldReferenceId:
              type: string
            fieldType:
              type: string
              enum:
                - systemId
            operator:
              type: string
              enum:
                - in
            value:
              type: array
              items:
                type: string
    ExportRunStartResponse:
      type: object
      description: >
        The run to poll after starting an export run. `outcome` is a policy
        verdict

        delivered as a successful `200`, not an error: `duplicate` means a run

        producing this exact export (same request, same configuration version)
        was

        already in flight, so `runId` is that run and no second export was
        started.
      required:
        - runId
        - outcome
      properties:
        runId:
          type: string
          format: uuid
          description: >-
            The run to poll via the start endpoint's GET .../export-runs/{runId}
            sibling
        outcome:
          type: string
          enum:
            - enqueued
            - duplicate
          description: >-
            `enqueued` when a new export was started; `duplicate` when a run
            already in flight was producing this exact export (pass ?force=true
            to start a new run anyway)
    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
    ExportRunsTooManyInFlightResponse:
      type: object
      description: >
        The `429` body when a company already has the maximum number of export
        runs in

        flight. It is the standard error envelope plus `inFlightRunIds`, so a
        client

        can poll the runs that are already running instead of retrying blind.
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
            - inFlightRunIds
          properties:
            code:
              type: string
              description: Machine-readable error code
              example: TooManyActiveExportRuns
            message:
              type: string
              description: Human-readable error message
            userMessages:
              type: array
              description: Clean, verbatim-displayable messages
              items:
                type: string
            inFlightRunIds:
              type: array
              description: >-
                The ids of the runs already in flight (`queued` or `running`)
                for this company. Poll these instead of retrying; start again
                once one reaches a terminal status.
              items:
                type: string
                format: uuid
  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`.

````