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

# Attach a new or existing file to a supported destination

> Available when the file-attachment rollout is enabled for the caller's organization. Call with a target and exactly one file source. Existing authorized Govly file references attach immediately. A new file's metadata returns status upload_required and a 15-minute signed Govly URL. The host POSTs bytes using exactly requiredHeaders, then calls this same operation with the same target and file type upload plus uploadId. The byte request needs no OAuth header or API key. File contents never enter tool arguments. Metadata preparation creates a new pending upload on each call. Upload completion retries return the same fileId while the token is valid; reference retries return the same attachment for the same blob and target. Every retry rechecks permissions. Unattached upload blobs are scheduled for cleanup after 24 hours; attached files are retained. All MIME types are allowed; validation checks declared metadata, not file format or malware.




## OpenAPI

````yaml /openapi/tools-v1.yaml post /api/tools/v1/file_attachments
openapi: 3.1.0
info:
  title: Govly Tools API
  version: 1.0.0-alpha
  description: >
    ALPHA / UNSTABLE: This API is still in active development. Endpoint
    behavior, request fields, response fields, error codes, and operation names
    may change before the Tools API is declared stable.

    REST-callable tool surface for agent and automation workflows. Agents are
    the primary consumer, but integrations can be built on this API. Responses
    are JSON for typed clients; MCP tools may render action results into
    text-oriented formats separately.

    Validating requests: validate against this schema in your client before
    sending. Govly ignores a request field it does not recognize rather than
    rejecting it, so a misspelled filter name is not applied — the response
    returns 200 with a broader result set than you intended, and nothing marks
    the difference. Where a request body declares `additionalProperties: false`,
    strict client-side validation is what catches that. Fields sent with the
    wrong type are rejected with 400 on most endpoints; validate types in your
    client too rather than relying on it.

    Rate limits: each resource (for example awards, opportunities, or
    workspaces) allows 70 requests per minute per user. Exceeding it returns 429
    with the standard error envelope, `code: rate_limited`, and a `Retry-After`
    header. Keys sent in the `X-API-KEY` header are also subject to the
    Enterprise API limit of 300 requests per minute per key; see the Rate Limits
    page.
servers:
  - url: https://app.govly.com
security:
  - bearerApiKey: []
  - headerApiKey: []
tags:
  - name: Opportunities
    description: Search, fetch, and inspect Govly opportunity records.
  - name: Awards
    description: Search and inspect awarded government contracts.
  - name: Contacts
    description: Search and inspect government points of contact.
  - name: Signals
    description: Search clustered procurement and market intelligence signals.
  - name: Places
    description: Resolve place names to canonical Govly Place ids.
  - name: Product Catalogs
    description: List government contract price lists and search their line items.
  - name: Workspaces
    description: Create, update, and inspect opportunity workspaces.
  - name: Organization Users
    description: Discover the members of your organization and their account status.
  - name: Workspace Members
    description: Add users and teams to workspaces.
  - name: File Attachments
    description: >-
      Attach new or existing files through a signed Govly transfer or an
      authorized reference.
  - name: Workspace Attachments
    description: List and upload workspace attachments.
  - name: Workspace Comments
    description: Post comments to workspaces.
  - name: Organization Labels
    description: List, create, rename, recolor, and delete the organization's labels.
  - name: Record Labels
    description: >-
      Apply and remove the organization's labels on opportunities, awards,
      contacts, and workspaces.
  - name: Follows
    description: Follow opportunities and related workspace activity.
  - name: Shares
    description: Share opportunities, awards, and contacts with colleagues by email.
  - name: Saved Searches
    description: List saved opportunity searches and cached matches.
  - name: Documents
    description: >-
      Read document representations and request temporary original-file
      downloads.
  - name: Quote Submissions
    description: >-
      Inspect quote submission requirements, submit quotes, and poll submission
      status.
  - name: Inbox
    description: Read and triage the authenticated user's matched inbox items.
paths:
  /api/tools/v1/file_attachments:
    post:
      tags:
        - File Attachments
      summary: Attach a new or existing file to a supported destination
      description: >
        Available when the file-attachment rollout is enabled for the caller's
        organization. Call with a target and exactly one file source. Existing
        authorized Govly file references attach immediately. A new file's
        metadata returns status upload_required and a 15-minute signed Govly
        URL. The host POSTs bytes using exactly requiredHeaders, then calls this
        same operation with the same target and file type upload plus uploadId.
        The byte request needs no OAuth header or API key. File contents never
        enter tool arguments. Metadata preparation creates a new pending upload
        on each call. Upload completion retries return the same fileId while the
        token is valid; reference retries return the same attachment for the
        same blob and target. Every retry rechecks permissions. Unattached
        upload blobs are scheduled for cleanup after 24 hours; attached files
        are retained. All MIME types are allowed; validation checks declared
        metadata, not file format or malware.
      operationId: attach_file
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FileAttachmentInput'
      responses:
        '200':
          description: >-
            Pending transfer or completed attachment; inspect data.status before
            reporting success.
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                properties:
                  data:
                    oneOf:
                      - $ref: '#/components/schemas/FileUploadRequired'
                      - $ref: '#/components/schemas/FileAttached'
        '401':
          $ref: '#/components/responses/Error'
        '403':
          $ref: '#/components/responses/Error'
        '404':
          $ref: '#/components/responses/Error'
        '422':
          $ref: '#/components/responses/Error'
        '429':
          $ref: '#/components/responses/RateLimited'
        '503':
          $ref: '#/components/responses/Error'
components:
  schemas:
    FileAttachmentInput:
      type: object
      additionalProperties: false
      required:
        - target
        - file
      properties:
        target:
          $ref: '#/components/schemas/FileAttachmentTarget'
        file:
          $ref: '#/components/schemas/FileAttachmentSource'
    FileUploadRequired:
      type: object
      required:
        - status
        - target
        - uploadId
        - uploadUrl
        - method
        - requiredHeaders
        - expiresAt
        - instructions
      properties:
        status:
          type: string
          const: upload_required
        target:
          $ref: '#/components/schemas/FileAttachmentTarget'
        uploadId:
          type: string
          description: >-
            Opaque expiring upload capability bound to the creating actor and
            selected target.
        uploadUrl:
          type: string
          format: uri
          description: >-
            Signed Govly URL authorizing byte transfer without additional
            credentials.
        method:
          type: string
          const: POST
        requiredHeaders:
          type: object
          additionalProperties:
            type: string
          description: >-
            Send these header names/values unchanged, including
            application/octet-stream and exact Content-Length. No OAuth/API-key
            header or multipart body.
        expiresAt:
          type: string
          format: date-time
        instructions:
          type: string
    FileAttached:
      type: object
      required:
        - status
        - fileId
        - fileRef
        - target
        - targetUrl
        - workspaceId
        - workspaceUrl
        - filename
        - contentType
        - byteSize
        - textExtractStatus
      properties:
        status:
          type: string
          const: attached
        fileId:
          type: string
          description: >-
            Workspace attachment ID, usable with
            document_read/document_download.
        fileRef:
          type: string
          description: >-
            workspace_attachment:<id> reference for subsequent attach_file
            calls.
        target:
          $ref: '#/components/schemas/FileAttachmentTarget'
        targetUrl:
          type: string
          format: uri
          description: >-
            Govly page containing the target. Comments link to the containing
            workspace.
        workspaceId:
          type: string
        workspaceUrl:
          type: string
          format: uri
          description: Use this returned link in user-facing responses.
        commentId:
          type:
            - string
            - 'null'
        filename:
          type: string
        contentType:
          type: string
        byteSize:
          type: integer
        textExtractStatus:
          type: string
          description: Text extraction may still be processing after attachment succeeds.
    FileAttachmentTarget:
      type: object
      additionalProperties: false
      required:
        - type
        - id
      properties:
        type:
          type: string
          enum:
            - workspace
            - workspace_comment
          description: >-
            Explicitly supported attachment destination. Comments must already
            exist and require edit permission.
        id:
          type: string
          pattern: ^[1-9][0-9]*$
          description: >-
            Target record ID. Pending uploads cannot be redirected to another
            target.
    FileAttachmentSource:
      anyOf:
        - type: object
          additionalProperties: false
          required:
            - type
            - filename
            - contentType
            - fileSize
            - checksum
          properties:
            type:
              type: string
              const: new
            filename:
              type: string
              description: >-
                Nonempty filename, at most 255 bytes, without paths or control
                characters.
            contentType:
              type: string
              description: MIME type without parameters, e.g. application/pdf.
            fileSize:
              type: integer
              minimum: 1
              maximum: 52428800
              description: Exact host-computed file size in bytes (maximum 50 MiB).
            checksum:
              type: string
              description: Host-computed base64 MD5 digest, never base64 file contents.
        - type: object
          additionalProperties: false
          required:
            - type
            - uploadId
          properties:
            type:
              type: string
              const: upload
            uploadId:
              type: string
              description: >-
                Opaque uploadId from an upload_required result; transfer bytes
                first and resume within 15 minutes.
        - type: object
          additionalProperties: false
          required:
            - type
            - fileRef
          properties:
            type:
              type: string
              const: reference
            fileRef:
              type: string
              pattern: ^(session_attachment|workspace_attachment):[1-9][0-9]*$
              description: >-
                Reference to an authorized owning record, never a raw blob ID.
                Govly AI session references are scoped to its current session.
    ErrorEnvelope:
      type: object
      required:
        - errors
      properties:
        errors:
          type: array
          items:
            type: object
            required:
              - status
              - code
              - title
              - detail
            properties:
              status:
                type: string
              code:
                type: string
              title:
                type: string
              detail:
                type: string
              source:
                type: object
                properties:
                  pointer:
                    type: string
    RateLimitError:
      type: object
      required:
        - error
      properties:
        error:
          type: string
  responses:
    Error:
      description: Error response
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    RateLimited:
      description: >
        Too many requests. Two limiters can produce this status and they use
        different bodies. The per-user limit of 70 requests per minute for each
        resource returns the standard error envelope with `code: rate_limited`
        and a `Retry-After` header. Keys sent in the `X-API-KEY` header are also
        subject to the Enterprise API limit of 300 requests per minute per key,
        which returns the plain `error` form with `Retry-After` and the
        `X-RateLimit-*` headers. Clients should accept either body.
      headers:
        Retry-After:
          description: Seconds to wait before retrying.
          schema:
            type: string
      content:
        application/json:
          schema:
            oneOf:
              - $ref: '#/components/schemas/ErrorEnvelope'
              - $ref: '#/components/schemas/RateLimitError'
  securitySchemes:
    bearerApiKey:
      type: http
      scheme: bearer
      bearerFormat: API key
    headerApiKey:
      type: apiKey
      in: header
      name: X-API-KEY

````

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