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

# Submit File

> Uploads a file and attaches it to a property.

This endpoint takes `multipart/form-data`, not JSON: the metadata fields below are form fields sent alongside the file, and a JSON body is rejected. Only one file is accepted per request.

At least one of `address`, `parcelId`, or `coordinates` is required, except for Elevation Certificates, where the location is read out of the certificate.

Supply as many as you have. Address plus parcel ID plus coordinates matches far more reliably than any one alone, and they are used together to find or create the property.



## OpenAPI

````yaml /developers/v1/openapi.json post /api/v1/files
openapi: 3.1.0
info:
  title: Forerunner Integration API v1
  version: 1.0.0
  description: >-
    Read and write floodplain data in Forerunner. This is the v1 contract; each
    version is documented separately and evolves on its own.


    v1 is the current version. It covers files, properties, records, and SI/SD,
    and is the one to build against. Its record endpoints handle `Log` records
    only; use v2 for any other record type.


    Every request needs an `Authorization: Bearer <your API key>` header.


    List endpoints return 25 results per page; page through them with `page` and
    read `pageInfo` for the totals. Every JSON response carries an `errors`
    array, empty when the request succeeded; the `401`, `403`, and `429`
    responses are plain text or HTML instead.


    Develop against the staging server, which is a separate account with
    separate API keys and separate data.


    Requests are rate limited per IP at the CDN. A request over the limit is
    answered with a `429` and an HTML body, not the JSON error shape.
servers:
  - url: https://app.withforerunner.com
    description: Production
  - url: https://app.staging.withforerunner.com
    description: Staging, for development and testing
security:
  - bearerAuth: []
tags:
  - name: Files
    description: >-
      Upload, retrieve, and update documents such as Elevation Certificates and
      permits.
  - name: Properties
    description: Query the properties in your account.
  - name: Records
    description: >-
      Read, create, update, and delete `Log` records. Other record types are
      available on v2.
  - name: SI/SD
    description: >-
      Track substantial improvement and substantial damage against your
      community's thresholds.
paths:
  /api/v1/files:
    post:
      tags:
        - Files
      summary: Submit File
      description: >-
        Uploads a file and attaches it to a property.


        This endpoint takes `multipart/form-data`, not JSON: the metadata fields
        below are form fields sent alongside the file, and a JSON body is
        rejected. Only one file is accepted per request.


        At least one of `address`, `parcelId`, or `coordinates` is required,
        except for Elevation Certificates, where the location is read out of the
        certificate.


        Supply as many as you have. Address plus parcel ID plus coordinates
        matches far more reliably than any one alone, and they are used together
        to find or create the property.
      operationId: uploadFile
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                fileUpload:
                  type: string
                  format: binary
                  description: >-
                    The file to upload. Which media types you can send depends
                    on the document type configured for `fileType`.


                    Each type has its own size limit, and a file over its limit
                    is rejected:


                    - `application/pdf`, `image/jpeg`, `image/png`, `image/jpg`
                    — up to 30 MB

                    - `application/json`, `application/geo+json`, `text/csv` —
                    up to 100 MB

                    - `video/mp4`, `video/quicktime` — up to 600 MB

                    - `application/geopackage+vnd.sqlite3`, `application/zip`,
                    `application/vnd.shp` — up to 1000 MB
                fileType:
                  type: string
                  description: >-
                    Document type name, such as `Elevation Certificate`,
                    `Building Permit`, or `Property Image`. Must match a
                    document type configured for your account; see [File
                    types](/files/file-types) for how they are set up.
                  example: Elevation Certificate
                mimeType:
                  type: string
                  description: Media type of the file.
                  example: application/pdf
                address:
                  description: >-
                    Street address to attach the file to, as `{number} {name}
                    {postfix}, {city}, {state} {zip}`.
                  example: 123 Main St, Springfield, IL 62701
                  type:
                    - string
                    - 'null'
                parcelId:
                  description: Parcel number to attach the file to.
                  example: 12-34-567-890
                  type:
                    - string
                    - 'null'
                externalSystemId:
                  description: >-
                    Your system's identifier for this file. Uploading a second
                    file with an identifier already in use returns 409.
                  example: EC-2024-0417
                  type:
                    - string
                    - 'null'
                externalDocumentURL:
                  description: >-
                    Link to display this file in your system. Public website
                    users will be directed here when viewing the file.
                  example: https://permits.example.gov/documents/EC-2024-0417
                  anyOf:
                    - type: string
                      format: uri
                    - type: 'null'
                coordinates:
                  anyOf:
                    - type: string
                      description: >-
                        A JSON-encoded `[latitude, longitude]` tuple in
                        EPSG:4326, to attach the file to that location.
                      example: '[39.7817, -89.6501]'
                    - type: 'null'
              required:
                - fileUpload
                - fileType
      responses:
        '200':
          description: Success. `errors` is empty.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V1FilePOSTResponse'
              example:
                errors: []
                file:
                  id: f8a3b2c1-d4e5-4789-abcd-ef0123456789
                  url: >-
                    https://demoville.app.withforerunner.com/files/f8a3b2c1-d4e5-4789-abcd-ef0123456789
        '400':
          description: The request failed validation. `errors` names each field at fault.
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '#/components/schemas/V1FilePOSTResponse'
                  - $ref: '#/components/schemas/APIResponse'
              example:
                errors:
                  - message: Required
                    field: fileUpload
                file: null
        '401':
          description: >-
            Missing or invalid API key. The body is plain text, not the JSON
            error shape.
        '403':
          description: >-
            Blocked by our web application firewall, which answers with an HTML
            body rather than the JSON error shape. Most often caused by a client
            sending a `PostmanRuntime`, `python-requests`, or `HeadlessChrome`
            `User-Agent`; clear that header and retry.
        '409':
          description: >-
            Another resource already uses that `externalSystemId`. Nothing was
            created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V1FilePOSTResponse'
              example:
                errors:
                  - message: >-
                      Document upload already exists with external system id
                      2024-0417
                    field: externalSystemId
                file: null
        '429':
          description: >-
            Too many requests from your IP. Rate limiting is applied at the CDN,
            so the body is HTML rather than the JSON error shape. Back off and
            retry.
components:
  schemas:
    V1FilePOSTResponse:
      type: object
      properties:
        errors:
          type: array
          items:
            $ref: '#/components/schemas/APIError'
          description: >-
            Empty when the request succeeded. Otherwise one entry per failure,
            and the resource fields on the response are empty: `null` for single
            resources, `[]` for lists, with `pageInfo` omitted.
          example: []
        file:
          anyOf:
            - $ref: '#/components/schemas/V1UploadedFileReference'
            - type: 'null'
          description: The uploaded file. Null when the upload failed.
      required:
        - errors
        - file
      additionalProperties: false
    APIResponse:
      type: object
      properties:
        errors:
          type: array
          items:
            $ref: '#/components/schemas/APIError'
          description: >-
            Empty when the request succeeded. Otherwise one entry per failure,
            and the resource fields on the response are empty: `null` for single
            resources, `[]` for lists, with `pageInfo` omitted.
          example: []
      required:
        - errors
      additionalProperties: false
      description: Every response carries an `errors` array alongside its resource fields.
    APIError:
      type: object
      properties:
        message:
          type: string
          description: Human-readable description of what went wrong.
          example: Required
        field:
          type: string
          description: The request field that caused the error, as a dot-separated path.
          example: data.type
      required:
        - message
        - field
      additionalProperties: false
      description: A single validation or processing failure.
    V1UploadedFileReference:
      type: object
      properties:
        id:
          type: string
          description: UUID of the newly uploaded file.
          example: f8a3b2c1-d4e5-4789-abcd-ef0123456789
        url:
          type: string
          description: Link to the new file's page in Forerunner.
          example: >-
            https://demoville.app.withforerunner.com/files/f8a3b2c1-d4e5-4789-abcd-ef0123456789
      required:
        - id
        - url
      additionalProperties: false
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Your account's API key, sent as `Authorization: Bearer <your API key>`.
        Keys are issued per environment, so a staging key will not work against
        production.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.