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

# List 1099s

> Lists the authenticated company's locally tracked vendor 1099 filing records, including
records awaiting confirmation and records marked not required. Each record exists before
a PDF is prepared. Requires API access: Manage and Taxes: View. Standard authentication,
live membership permissions, rate limits, monthly limits, and usage logging apply.

Without year, returns a page across all available years and summaries for every existing
annual report, newest year first. With year, returns only that year's records and one
summary. Existing reports with zero required records have summary filing_status
not_required, matching the UI's tracked-record count; this is not an independent legal
assessment or guarantee that all transactions have been imported. A requested year without
a report has summary filing_status unknown, zero tracked counts, and data []. Without
year and without reports, both summaries and data are []. No year defaults implicitly.

Summaries depend only on year, not vendor, filing_status, pending, filed_elsewhere, limit,
or starting_after. They cover the entire selected annual report(s), never just the current
page. Other filters affect data only. All filters combine with AND, except comma-separated
filing_status values combine with OR. No default hides not_required records.

Records are ordered by year descending, then stable record creation ID descending.
Paging is not a frozen snapshot. Cursors are bound to the authenticated company and
normalized record filters; use the same filters on each page. A changed limit is allowed.
Invalid filters or malformed, foreign, or differently scoped cursors return 400
invalid_request. Empty results have has_more false and next_cursor null.

Vendor names are display names, not unique identities. The current workflow tracks
merchant/category groups, so the same vendor name can appear in multiple records for
the same year. Counts describe tracked filing records, not deduplicated legal recipients.
Individual records can be retrieved directly by their f1099_ IDs without a report ID.

GET never generates reports, refreshes vendors, backfills IDs, files forms, or sends
W-9 requests. Historical public IDs must be backfilled before release. A selected annual
report with a missing or out-of-range reporting year (outside 1000–9999), missing
identities, or unsupported workflow states returns 503 forms_not_ready, even when
the report has no vendor records;
retry later. Available files have signed download links valid for five minutes; retrieve
the record again to refresh expired links. Filing status does not guarantee PDF availability.




## OpenAPI

````yaml /openapi.yaml get /forms/1099
openapi: 3.0.3
info:
  title: Finta API
  version: '1.0'
  description: >
    The Finta API provides programmatic access to your company's financial data,

    including transactions, journal entries, categories, financial reports, and
    the team directory.


    ## Authentication


    Each API key is scoped to a single company. There is no company ID
    parameter.

    The key already knows which company it belongs to. If you have access to
    multiple

    companies, create a separate key for each.


    A key acts as its owner; it does not have a separate permission snapshot.
    The owner

    must currently have **API access: Manage**, plus the permission required by
    the endpoint:


    | Endpoint | Required permission |

    |----------|---------------------|

    | `GET /company` | Company: View |

    | `GET /taxes`, `GET /taxes/{id}` | Taxes: View |

    | `GET /team` | Team & access: View |

    | `DELETE /team/invitations/{id}` | Team & access: Manage; target-management
    limits apply. No additional Growth/RBAC gate. |

    | `POST /team/invitations/{id}/resend` | Team & access: Manage;
    target-management limits apply. No additional Growth/RBAC gate. |

    | `PATCH /team/invitations/{id}` | Team & access: Manage; RBAC and
    active/trialing Growth required, with grant and target limits. |

    | `POST /team/invitations` | Team & access: Manage; requested grants must
    also be allowed for the person and plan. |

    | `GET /categories`, `GET /departments`, `GET /rules`, `GET /rules/{id}` |
    Accounting setup: View |

    | `POST /rules` | Accounting setup: Manage; applying to existing
    transactions (`apply_to_existing_transactions`, default true) also requires
    Transactions: Manage |

    | `PATCH /rules/{id}` | Accounting setup: Manage; Transactions: Manage is
    not required |

    | `DELETE /rules/{id}` | Accounting setup: Manage and Transactions: Manage,
    including absent retries |

    | `GET /integrations` | Integrations: View |

    | `GET /reports/*` | Reports: View |

    | `GET /accounts`, `GET /cards`, `GET /transactions`, `GET
    /transactions/{id}` | Transactions: View |

    | `GET /forms/1099`, `GET /forms/1099/{id}` | Taxes: View |

    | `POST /transactions/bulk/update`, `GET /jobs/{id}` | Transactions: Manage
    |

    | `PATCH /transactions/{id}`, `POST /accounts`, `POST /transaction_uploads`
    | Transactions: Manage |

    | `GET /journal_entries`, `GET /journal_entries/{id}`, `GET
    /aggregations/total`, `GET /aggregations/totals`, `GET /parties/merchants` |
    Reports: View |

    | `GET /invoices`, `GET /invoices/{id}` | Invoices: View |

    | `POST /invoices`, `POST /invoices/{id}/void` | Invoices: Manage |

    | `POST /invoices/{id}/match`, `POST /invoices/{id}/unmatch` | Invoices:
    Manage and Transactions: Manage |


    Permission changes apply to the next request. Removing API access
    permanently revokes

    the owner's active keys for that company; restoring access requires creating
    a new key.


    Authenticate by including your API key in the `Authorization` header:


    ```

    Authorization: Bearer finta_...

    ```


    ### Key prefix convention


    Every Finta credential is prefixed so it can be recognized at a glance in
    logs, error messages, and secret scanners. Today there is one credential
    type and its prefix is `finta_`. As additional credential or token types are
    introduced (for example restricted keys or webhook signing secrets), each
    will have its own distinct prefix that stacks on the brand prefix (e.g.
    `finta_<type>_...`). Treat the prefix as load-bearing: do not strip it
    before sending, and do not assume a missing or unknown prefix is still a
    Finta credential.


    ## Rate Limits


    The API enforces two independent limits. Both surface as `429 Too Many
    Requests`, but they are distinct error codes with different retry guidance.


    ### Per-minute burst limit


    Authenticated requests are limited to **6,000 requests per 60 seconds** (100
    per second) per API key. Unauthenticated requests (missing or invalid key)
    are limited to **120 requests per 60 seconds** per IP address.


    The window is **fixed**, not rolling. Each 60-second wall-clock interval is
    its own counter; all requests within that interval share it, and the counter
    resets to 0 in a single step at the next boundary. Available budget jumps
    from `0` back to the full bucket size (`6000` for authenticated API keys,
    `120` for unauthenticated IP buckets) instantaneously at the boundary,
    rather than aging out one slot at a time. Trust `X-RateLimit-Reset` for the
    exact reset timestamp.


    Successful responses and burst-limit rejections include the following
    headers.

    Do not assume they are present on other errors: early authentication,
    authorization,

    and monthly-limit rejections can omit them. This describes existing header
    behavior,

    not a new quota policy.


    | Header | Description |

    |--------|-------------|

    | `X-RateLimit-Limit` | Maximum requests per window (`6000` for
    authenticated requests, `120` for unauthenticated). |

    | `X-RateLimit-Remaining` | Requests remaining in the current window. |

    | `X-RateLimit-Reset` | Unix timestamp when the window resets. |


    On a 429 for this case, an additional header is included:


    | Header | Description |

    |--------|-------------|

    | `Retry-After` | Number of seconds until the next request is safe. |


    The error body is `type: rate_limit_error` / `code: rate_limit_exceeded`.


    **Retry guidance:** This case is retryable. Honor `Retry-After` as the
    minimum wait, then apply exponential backoff with jitter for any retries
    beyond the first (cap at a few minutes; abandon after a small number of
    attempts to avoid retry storms). Do not retry tighter than `Retry-After`.


    ### Monthly per-company limit


    Each company has a monthly cap on total API calls, independent of the
    per-minute burst:


    | Plan | Monthly cap |

    |------|-------------|

    | Formation | 10 |

    | Startup | 300 |

    | Growth | 30,000 |


    Counts reset at **midnight Pacific Time (US & Canada)** on the 1st of each
    month. This is the Finta application's configured time zone; the cap is
    computed in that zone, not in UTC. Consumers in other time zones should
    convert the local-midnight Pacific boundary to their own clock; note that
    the absolute UTC offset shifts by one hour twice a year for daylight saving
    (PST is UTC-8, PDT is UTC-7). Blocked requests are not counted toward the
    limit. The error body is `type: limit_error` / `code:
    monthly_limit_exceeded`, and the `message` field includes the reset date in
    human-readable form.


    **Retry guidance:** This case is **not retryable in the short term.** No
    `Retry-After` header is sent, deliberately, because the only meaningful
    remediation is to upgrade the plan (Settings -> Plans at app.finta.com) or
    wait until the 1st of the next month. Naive retry loops should branch on
    `error.code` and stop retrying when they see `monthly_limit_exceeded`. SDKs
    that auto-retry on 429 should look at `error.code` (or the absence of
    `Retry-After`) before re-issuing.


    A temporary company limit override, set by Finta support for the current
    month, may change

    the allowance and the wording of the monthly-limit message. It applies to
    every user and

    API key in the company. The error code and no-short-term-retry rule remain
    unchanged.


    ## Pagination


    List endpoints use cursor-based pagination. Pass `limit` to control page
    size

    (default 100, max 500). To fetch the next page, pass `starting_after` with
    the

    `next_cursor` value from the previous response. Responses include `object:
    "list"`,

    `url` (the canonical path of the collection, relative to the API host),
    `has_more`

    (whether more results exist), `next_cursor` (an opaque value to pass
    unchanged as `starting_after`),

    and `data` (the page of items).


    ## Amounts


    Every monetary field in the API follows two non-negotiable rules:


    1. **Integer cents.** Monetary values are integers, never floats and never
    formatted strings. `$499.00` is `49900`. `$1,500.00` is `150000`. Divide by
    100 to get dollars. This avoids floating-point precision errors in financial
    calculations.

    2. **`_cents` suffix.** The field name always ends in `_cents` (e.g.
    `amount_cents`, `balance_cents`, `total_cents`, `net_income_cents`,
    `change_in_cash_cents`, `cash_cents`). If a field name does not end in
    `_cents`, it is not a monetary value.


    These rules apply to every monetary field across every endpoint
    (transactions, journal entries, income statement, balance sheet, cash flow).
    There are no exceptions and there is no "summary" or "display" sibling field
    that returns the same amount in dollars or as a string. If you encounter a
    field that appears to hold a monetary value but does not end in `_cents`, or
    whose value is not an integer, treat it as a bug and report it.


    Sign conventions:


    - **Income statement**: revenue/income amounts are positive, expense amounts
    are negative. Summing every section's `total_cents` yields net income
    without sign-flipping.

    - **Balance sheet**: `balance_cents` carries the natural-sign cumulative
    balance for that account at the report date.

    - **Cash flow**: `amount_cents` is positive for cash inflows and negative
    for cash outflows.


    ## Errors


    Errors return a consistent JSON structure:


    ```json

    {
      "error": {
        "type": "invalid_request_error",
        "code": "resource_missing",
        "message": "The requested resource was not found.",
        "doc_url": "https://www.finta.com/docs/api-reference/errors#resource_missing"
      }
    }

    ```


    ### Status codes


    | Status | Meaning |

    |--------|---------|

    | `200 OK` | Request succeeded. |

    | `201 Created` | A new resource was created, such as an invitation, an
    account, or a transaction upload draft. |

    | `400 Bad Request` | Request was malformed or had invalid parameters. |

    | `401 Unauthorized` | The bearer credential is missing, malformed, or
    unrecognized. The fix is to obtain a valid API key. |

    | `403 Forbidden` | The API key is valid, but the caller does not have
    permission to access the resource. The fix is to regain the required company
    or product-area access. See the `Forbidden` response component for the
    specific codes. |

    | `404 Not Found` | The requested resource, or the endpoint itself, does not
    exist. Unknown or renamed paths (for example an old hyphenated report path
    like `/reports/income-statement` instead of `/reports/income_statement`)
    return this same envelope with `type: invalid_request_error` and `code:
    resource_missing`, as JSON, regardless of the `Accept` header. |

    | `422 Unprocessable Entity` | Invitation data failed validation, for
    example an invalid email or a conflicting invitation or existing teammate. |

    | `429 Too Many Requests` | Either the per-minute burst rate limit
    (retryable, with `Retry-After`) or the monthly per-company API call limit
    (not retryable in the short term, no `Retry-After`). Branch on `error.code`
    to distinguish the two and avoid retry storms on monthly exhaustion. See the
    Rate Limits section for the full retry guidance. |

    | `5xx` | An unexpected error on Finta's side. Retry with exponential
    backoff. |


    The `error.type` and `error.code` fields are stable identifiers safe to
    switch on programmatically. The `error.message` is human-readable and may
    change without notice.


    ### Early access endpoints


    Some endpoints are in early access: documented here, but turned on per
    company while they roll

    out. For a company that doesn't have one yet, every request to it returns
    `403 Forbidden` with

    `type: permission_error` and `code: feature_disabled`, ahead of the
    endpoint's own permission

    check, and changes nothing:


    ```json

    {
      "error": {
        "type": "permission_error",
        "code": "feature_disabled",
        "message": "This feature isn’t turned on for this company yet. Contact Finta to request access.",
        "doc_url": "https://www.finta.com/docs/api-reference/errors#feature_disabled"
      }
    }

    ```


    It is not retryable: contact Finta to request access for the company, then
    retry. Once

    the feature is on for the company the endpoint works normally, with no
    change to requests.
servers:
  - url: https://app.finta.com/api/v1
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Company
    description: Retrieve company metadata
  - name: Team
    description: Retrieve company members and manage invitations
  - name: Categories
    description: List your chart of accounts categories
  - name: Rules
    description: Company automation rule definitions.
  - name: Departments
    description: List the departments available to the authenticated company
  - name: Integrations
    description: List the authenticated company's integrations and their connection status
  - name: Aggregations
    description: >-
      Compute totals for one category and its descendants, as a single figure or
      grouped by merchant or month
  - name: Transactions
    description: >
      Transactions are what your bank shows you: a single line like "AWS charged
      you $499."

      Most API consumers want transactions. For accounting-level detail, see
      Journal Entries.


      Amounts are in cents (e.g. `amount_cents: 49900` = $499.00).
  - name: Journal Entries
    description: >
      Journal entries are the accounting records that transactions create. A
      single $499 AWS

      charge becomes two journal entries: debit Software $499, credit Cash $499
      (double-entry

      bookkeeping). Use journal entries when you need accounting-level detail.


      Amounts are in cents (e.g. `amount_cents: 49900` = $499.00).
  - name: Invoices
    description: >
      Invoices the company sent, and the bank deposits that paid them. Recording
      an invoice books

      its revenue; Finta doesn't send invoices to customers.


      Amounts are in cents (e.g. `amount_cents: 49900` = $499.00).
  - name: Parties
    description: Discover observed counterparties for category-scoped financial queries.
  - name: Forms
    description: Discover vendor compliance filing records and yearly progress.
  - name: Reports
    description: >
      Financial statements: income statement, balance sheet, and cash flow. Each
      report

      returns the complete statement for a single period. You cannot filter to
      one category

      or request multiple periods in one call.
  - name: Feedback
    description: Send questions, feedback and bug reports to Finta support
  - name: Taxes
    description: >-
      Discover income-tax and Delaware franchise-tax filing records and
      available PDFs.
paths:
  /forms/1099:
    get:
      tags:
        - Forms
      summary: List 1099s
      description: >
        Lists the authenticated company's locally tracked vendor 1099 filing
        records, including

        records awaiting confirmation and records marked not required. Each
        record exists before

        a PDF is prepared. Requires API access: Manage and Taxes: View. Standard
        authentication,

        live membership permissions, rate limits, monthly limits, and usage
        logging apply.


        Without year, returns a page across all available years and summaries
        for every existing

        annual report, newest year first. With year, returns only that year's
        records and one

        summary. Existing reports with zero required records have summary
        filing_status

        not_required, matching the UI's tracked-record count; this is not an
        independent legal

        assessment or guarantee that all transactions have been imported. A
        requested year without

        a report has summary filing_status unknown, zero tracked counts, and
        data []. Without

        year and without reports, both summaries and data are []. No year
        defaults implicitly.


        Summaries depend only on year, not vendor, filing_status, pending,
        filed_elsewhere, limit,

        or starting_after. They cover the entire selected annual report(s),
        never just the current

        page. Other filters affect data only. All filters combine with AND,
        except comma-separated

        filing_status values combine with OR. No default hides not_required
        records.


        Records are ordered by year descending, then stable record creation ID
        descending.

        Paging is not a frozen snapshot. Cursors are bound to the authenticated
        company and

        normalized record filters; use the same filters on each page. A changed
        limit is allowed.

        Invalid filters or malformed, foreign, or differently scoped cursors
        return 400

        invalid_request. Empty results have has_more false and next_cursor null.


        Vendor names are display names, not unique identities. The current
        workflow tracks

        merchant/category groups, so the same vendor name can appear in multiple
        records for

        the same year. Counts describe tracked filing records, not deduplicated
        legal recipients.

        Individual records can be retrieved directly by their f1099_ IDs without
        a report ID.


        GET never generates reports, refreshes vendors, backfills IDs, files
        forms, or sends

        W-9 requests. Historical public IDs must be backfilled before release. A
        selected annual

        report with a missing or out-of-range reporting year (outside
        1000–9999), missing

        identities, or unsupported workflow states returns 503 forms_not_ready,
        even when

        the report has no vendor records;

        retry later. Available files have signed download links valid for five
        minutes; retrieve

        the record again to refresh expired links. Filing status does not
        guarantee PDF availability.
      operationId: list1099s
      parameters:
        - name: year
          in: query
          description: >-
            Exact four-digit reporting year, not the year of submission. Omit to
            discover all available years.
          schema:
            type: integer
            minimum: 1000
            maximum: 9999
        - name: filing_status
          in: query
          description: >-
            One or more public record statuses separated by commas. Values are
            review_required, w9_required, w9_requested, ready_to_file, filing,
            filed, and not_required. Values combine with OR. pending is not an
            individual status; use the pending filter instead.
          schema:
            type: string
          example: w9_required,w9_requested
        - name: pending
          in: query
          description: >-
            Strict true or false. True includes w9_required, w9_requested,
            ready_to_file, and filing. False includes all other statuses,
            including unconfirmed and not-required records.
          schema:
            type: boolean
        - name: vendor_name
          in: query
          description: >-
            Case-insensitive exact vendor display-name match. Surrounding
            whitespace is ignored on both the query and stored name, so a
            returned vendor_name can be used directly as a filter. Returned
            display names are not rewritten. Blank names are invalid; names are
            not unique. No substring or fuzzy matching.
          schema:
            type: string
            minLength: 1
        - name: filed_elsewhere
          in: query
          description: >-
            Strict true or false. True selects filed records reported as
            completed outside Finta. False includes all other records, including
            pending records.
          schema:
            type: boolean
        - name: limit
          in: query
          schema:
            type: integer
            minimum: 1
            maximum: 500
            default: 100
        - name: starting_after
          in: query
          description: >-
            Opaque next_cursor from the previous response, passed unchanged and
            URL-encoded. Do not pass a form ID. Keep the same normalized filters
            on subsequent pages.
          schema:
            type: string
      responses:
        '200':
          description: A page of tracked 1099 records with complete yearly summaries.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Form1099List'
        '400':
          description: >-
            Invalid filter or cursor. error.param identifies the invalid
            parameter.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/RateLimited'
        '503':
          description: >-
            forms_not_ready. Selected reports require year/workflow data repair
            or record identity backfill, including empty reports with invalid
            years. GET does not repair them. Retry later.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    Form1099List:
      type: object
      additionalProperties: false
      required:
        - object
        - url
        - has_more
        - next_cursor
        - summaries
        - data
      properties:
        object:
          type: string
          enum:
            - list
        url:
          type: string
          enum:
            - /api/v1/forms/1099
        has_more:
          type: boolean
        next_cursor:
          type: string
          nullable: true
          description: Opaque cursor for the next page, or null when has_more is false.
        summaries:
          type: array
          description: >-
            Complete annual summaries, newest year first. Only year filters
            these; record filters and pagination do not. Explicit missing years
            have one unknown summary; unfiltered discovery lists only existing
            reports.
          items:
            $ref: '#/components/schemas/Form1099Summary'
        data:
          type: array
          items:
            $ref: '#/components/schemas/Form1099'
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - type
            - code
            - message
            - doc_url
          properties:
            type:
              type: string
              enum:
                - authentication_error
                - permission_error
                - invalid_request_error
                - rate_limit_error
                - limit_error
                - api_error
              description: >-
                The error category. `authentication_error` (401) means the
                bearer credential was missing, malformed, or unrecognized.
                `permission_error` (403) means the credential was valid but the
                caller is not allowed to access the resource.
                `invalid_request_error` covers invalid parameters, unavailable
                resources, invitation validation failures, and requests that
                conflict with current state (409). `rate_limit_error` is for
                per-minute burst limits (retry shortly). `limit_error` is for
                monthly API call limits per company (upgrade or wait for reset).
                `api_error` denotes an operation failure on the server (500), or
                temporarily unavailable rule definitions (503 rules_not_ready).
                Retry with exponential backoff; persistent 503 errors require
                operator attention.
            code:
              type: string
              enum:
                - invalid_api_key
                - user_inactive
                - user_removed_from_company
                - company_closed
                - subscription_required
                - staging_access_denied
                - insufficient_permission
                - resource_missing
                - parameter_missing
                - category_update_failed
                - transaction_update_failed
                - rate_limit_exceeded
                - monthly_limit_exceeded
                - invalid_date_range
                - invalid_date
                - invalid_request
                - idempotency_key_conflict
                - plan_upgrade_required
                - feature_disabled
                - invitation_invalid
                - invitation_create_failed
                - permissions_update_failed
                - invitation_resend_failed
                - invitation_revoke_failed
                - integration_not_connectable
                - integration_already_connected
                - connect_link_in_progress
                - connect_link_failed
                - rules_not_ready
                - forms_not_ready
                - taxes_not_ready
                - rule_already_exists
                - rule_busy
                - rule_deletion_failed
                - account_create_failed
                - upload_committed
                - upload_commit_failed
                - feedback_unavailable
                - closed_books
                - invoice_already_exists
                - invoice_not_open
                - invoice_not_matched
                - payment_already_matched
                - transaction_not_matchable
                - invoice_operation_failed
              description: A specific error code.
            message:
              type: string
              description: A human-readable description of the error.
            doc_url:
              type: string
              format: uri
              description: A link to documentation about this error.
              example: https://www.finta.com/docs/api-reference/errors#invalid_api_key
            param:
              type: string
              nullable: true
              description: The parameter that caused the error, if applicable.
    Form1099Summary:
      type: object
      additionalProperties: false
      required:
        - year
        - filing_status
        - counts
      properties:
        year:
          type: integer
          minimum: 1000
          maximum: 9999
        filing_status:
          type: string
          enum:
            - unknown
            - review_required
            - pending
            - filed
            - not_required
          description: >
            unknown means no report exists for the explicitly requested year,
            not no obligations.

            For existing reports, review_required means at least one record is
            unconfirmed and

            takes precedence over pending; pending means confirmed required
            filings remain

            incomplete; filed means all tracked required filings are complete
            and at least one

            is filed; not_required means there are no tracked required or
            unconfirmed records,

            including an empty report. These summarize Finta's known records,
            not a separate

            legal assessment. filing is counted as pending, never filed.
        counts:
          type: object
          additionalProperties: false
          required:
            - review_required
            - required
            - pending
            - filed
          properties:
            review_required:
              type: integer
              minimum: 0
              description: >-
                Records whose requirement has not been confirmed. Excluded from
                required and pending.
            required:
              type: integer
              minimum: 0
              description: >-
                Confirmed required records, including already filed. Always
                pending + filed. Excludes unconfirmed and not-required records.
            pending:
              type: integer
              minimum: 0
              description: >-
                Confirmed required records in w9_required, w9_requested,
                ready_to_file, or filing.
            filed:
              type: integer
              minimum: 0
              description: >-
                Completed tracked records, including reported filings outside
                Finta. Never includes filing in progress.
    Form1099:
      type: object
      additionalProperties: false
      required:
        - id
        - object
        - year
        - vendor_name
        - filing_status
        - filed_at
        - filed_elsewhere
        - documents
        - created
        - updated
      properties:
        id:
          type: string
          pattern: ^f1099_[A-Za-z0-9]+$
          description: >-
            Stable public filing-record identity. Issued IDs and their unique
            index are retained across schema rollback and reapplication.
        object:
          type: string
          enum:
            - form_1099
        year:
          type: integer
          minimum: 1000
          maximum: 9999
          description: Reporting year, independent of the year of filing.
        vendor_name:
          type: string
          description: >-
            Vendor display name. Not a unique recipient identity;
            merchant/category grouping can yield multiple same-name records in
            one year.
        filing_status:
          type: string
          enum:
            - review_required
            - w9_required
            - w9_requested
            - ready_to_file
            - filing
            - filed
            - not_required
          description: >
            review_required: whether filing is required needs confirmation.

            w9_required: confirmed required and waiting for W-9 collection, with
            no current

            W-9 request stage recorded through Finta.

            w9_requested: Finta recorded a W-9 request and the workflow is
            awaiting collection.

            ready_to_file: ready for the user to pay and request filing.

            filing: filing requested and processing, not completed.

            filed: recorded as complete through Finta or elsewhere; PDF may be
            unavailable.

            not_required: the record was marked as not requiring filing by the
            user or Finta.

            These are workflow stages, not an IRS acceptance or
            document-presence guarantee.
        filed_at:
          type: integer
          nullable: true
          description: >-
            Recorded filing time in Unix seconds for filings through Finta. Null
            if unknown, unfiled, or filed elsewhere. The time when a user marks
            filed elsewhere and updated are never substituted for a filing date.
        filed_elsewhere:
          type: boolean
          description: >-
            True only for records reported as filed outside Finta. Such records
            have filing_status filed and count toward filed totals. False for
            all other stages.
        documents:
          type: array
          description: >-
            Available attachments with signed links. Empty when none are
            available. Does not establish requirement, filing completion, or IRS
            acceptance; a filed record can have no documents.
          items:
            $ref: '#/components/schemas/Form1099Document'
        created:
          type: integer
          description: Unix seconds when this tracked filing record was created.
        updated:
          type: integer
          description: >-
            Unix seconds when the tracked workflow record was last modified. Not
            a guarantee that vendor names or all attachment changes have changed
            this timestamp; no incremental-sync filter is offered.
    Form1099Document:
      type: object
      additionalProperties: false
      required:
        - id
        - type
        - filename
        - content_type
        - download_url
        - expires_at
      properties:
        id:
          type: string
          pattern: ^doc_[a-f0-9]{24}$
          description: >-
            Stable opaque identity of the attached file. Link refreshes preserve
            it; replacing the file changes it. No standalone document endpoint
            is offered.
        type:
          type: string
          enum:
            - w9
            - form_1099
        filename:
          type: string
        content_type:
          type: string
          nullable: true
          description: Stored MIME type, if known. Do not assume every attachment is a PDF.
        download_url:
          type: string
          description: >-
            Signed URL usable without API authentication for five minutes.
            Retrieve the form again to refresh the URL after expiry.
        expires_at:
          type: integer
          description: >-
            Unix timestamp in seconds when the signed download link expires, not
            when the filing or stored file expires.
  responses:
    Unauthorized:
      description: >-
        Authentication failed. Returned when the bearer credential itself is
        missing, malformed, or unrecognized. The consumer should obtain a valid
        API key and retry. This is distinct from `403 Forbidden`, which is
        returned when the credential is valid but the caller is not allowed to
        access the resource.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              type: authentication_error
              code: invalid_api_key
              message: >-
                Invalid API key provided. Check that your API key is correct and
                active.
              doc_url: https://www.finta.com/docs/api-reference/errors#invalid_api_key
    Forbidden:
      description: >-
        The API key was successfully authenticated, but the caller is not
        allowed to access this resource. The fix is not "get a new key" (that
        returns 401) but "regain access" (reactivate the user, restore company
        access, restore an active subscription, or ask an administrator for the
        required product permission). These codes can be returned, distinguished
        by `error.code`:
          - `user_inactive` - the user that owns the API key has been deactivated.
          - `user_removed_from_company` - the user no longer has access to the company the key was created for.
          - `company_closed` - the company is closed, closing, or deleted.
          - `subscription_required` - the company does not have an active subscription.
          - `staging_access_denied` - the staging environment is restricted to Finta users.
          - `insufficient_permission` - the key owner lacks API access or the endpoint's required area permission.
          - `feature_disabled` - the endpoint is in early access and not yet turned on for this company; contact Finta to request access. See "Early access endpoints" under Errors.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            user_inactive:
              summary: User has been deactivated
              value:
                error:
                  type: permission_error
                  code: user_inactive
                  message: >-
                    The user associated with this API key is no longer active.
                    Reactivate the user or create a new API key under an active
                    user.
                  doc_url: >-
                    https://www.finta.com/docs/api-reference/errors#user_inactive
            user_removed_from_company:
              summary: User no longer has access to this company
              value:
                error:
                  type: permission_error
                  code: user_removed_from_company
                  message: >-
                    The user associated with this API key no longer has access
                    to this company. Ask a company admin to re-grant access,
                    then create a new API key.
                  doc_url: >-
                    https://www.finta.com/docs/api-reference/errors#user_removed_from_company
            company_closed:
              summary: Company is closed
              value:
                error:
                  type: permission_error
                  code: company_closed
                  message: >-
                    This company is closed. The API is not available for closed
                    companies.
                  doc_url: >-
                    https://www.finta.com/docs/api-reference/errors#company_closed
            subscription_required:
              summary: Company subscription is not active
              value:
                error:
                  type: permission_error
                  code: subscription_required
                  message: >-
                    This company does not have an active subscription. Visit
                    Settings -> Plans at app.finta.com to resolve, then retry.
                  doc_url: >-
                    https://www.finta.com/docs/api-reference/errors#subscription_required
            staging_access_denied:
              summary: Staging access is restricted
              value:
                error:
                  type: permission_error
                  code: staging_access_denied
                  message: This staging environment is restricted to Finta users.
                  doc_url: >-
                    https://www.finta.com/docs/api-reference/errors#staging_access_denied
            insufficient_permission:
              summary: Key owner lacks the required product permission
              value:
                error:
                  type: permission_error
                  code: insufficient_permission
                  message: >-
                    The API key owner needs the Transactions: View permission to
                    use this endpoint.
                  doc_url: >-
                    https://www.finta.com/docs/api-reference/errors#insufficient_permission
            feature_disabled:
              summary: Endpoint is in early access and not yet on for this company
              value:
                error:
                  type: permission_error
                  code: feature_disabled
                  message: >-
                    This feature isn’t turned on for this company yet. Contact
                    Finta to request access.
                  doc_url: >-
                    https://www.finta.com/docs/api-reference/errors#feature_disabled
    RateLimited:
      description: >-
        Too many requests. Two distinct limits can trigger a 429: (1) Per-minute
        burst limit (6,000 requests per 60 seconds per API key) returns
        `rate_limit_error` / `rate_limit_exceeded` with `Retry-After` header.
        (2) Monthly API call limit per company returns `limit_error` /
        `monthly_limit_exceeded` with the reset date in the message. Monthly
        limits vary by plan: Formation (10/month), Startup (300/month), Growth
        (30,000/month). Blocked requests do not count toward the limit.
      headers:
        Retry-After:
          schema:
            type: integer
          description: >-
            Seconds until the burst rate limit resets. Only present for
            rate_limit_error responses.
        X-RateLimit-Limit:
          schema:
            type: integer
          description: >-
            Maximum requests per burst window. Only present for rate_limit_error
            responses.
        X-RateLimit-Remaining:
          schema:
            type: integer
          description: >-
            Requests remaining in burst window (0 when rate limited). Only
            present for rate_limit_error responses.
        X-RateLimit-Reset:
          schema:
            type: integer
          description: >-
            Unix timestamp when the burst window resets. Only present for
            rate_limit_error responses.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            burst_rate_limit:
              summary: Per-minute burst rate limit exceeded
              value:
                error:
                  type: rate_limit_error
                  code: rate_limit_exceeded
                  message: >-
                    Too many requests. Please retry after the Retry-After
                    period.
                  doc_url: >-
                    https://www.finta.com/docs/api-reference/errors#rate_limit_exceeded
            monthly_limit:
              summary: Monthly API call limit exceeded
              value:
                error:
                  type: limit_error
                  code: monthly_limit_exceeded
                  message: >-
                    Monthly API limit reached. Your plan allows 300 calls per
                    company per month. Resets on April 1, 2026. Upgrade in
                    Settings -> Plans at app.finta.com.
                  doc_url: >-
                    https://www.finta.com/docs/api-reference/errors#monthly_limit_exceeded
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: API key prefixed with `finta_`

````

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