openapi: 3.0.3
info:
  title: FQ Data Platform Public API
  version: '2.0'
  license:
    name: Proprietary
    url: https://floqast.com
  contact:
    name: FloQast API Support
    url: https://support.floqast.com
  description: >-
    Public ingestion API for the FloQast Data Platform. Push financial data — GL
    accounts, balances, transactions, FX rates, companies, and subledger
    transactions — via the Direct-Connect channel, and manage the signatures
    (schema versions) that ingest requests target via `x-signature-id`.


    This is the published, customer-facing contract (auth: `x-api-key`). It is
    consumed by the FloQast developer portal via remote reference and is not the
    ingestion service's internal implementation spec.
servers:
  - url: https://apix.floqast.app/v2
    description: US Region
  - url: https://apix.eu.floqast.app/v2
    description: EU Region
  - url: https://apix.au.floqast.app/v2
    description: AU Region
security:
  - ApiKeyAuth: []
paths:
  /financial-data/signatures:
    post:
      operationId: createSignature
      summary: Create a signature
      tags:
        - Signatures
      security:
        - ApiKeyAuth: []
      description: >-
        Registers a new signature (schema version) for the caller's connector.
        The returned `id` is the value passed as the `x-signature-id` header on
        subsequent ingest requests. The connector is resolved from the API key —
        it is not supplied in the body.
      parameters:
        - $ref: '#/components/parameters/DataPlatformRequestId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateSignatureRequest'
            example:
              name: Primary GL Accounts signature
              description: Chart-of-accounts schema v2
              model: gl-accounts
              entityIds:
                - 507f1f77bcf86cd799439011
              customFields:
                - name: costCenter
                  type: string
      responses:
        '201':
          $ref: '#/components/responses/DataPlatformSignatureCreated'
        '400':
          $ref: '#/components/responses/DataPlatformBadRequest'
        '401':
          $ref: '#/components/responses/DataPlatformUnauthorized'
        '409':
          $ref: '#/components/responses/DataPlatformConflict'
        '413':
          $ref: '#/components/responses/DataPlatformBodyTooLarge'
        '422':
          $ref: '#/components/responses/DataPlatformValidationError'
        '500':
          $ref: '#/components/responses/DataPlatformInternalError'
        '502':
          $ref: '#/components/responses/DataPlatformBadGateway'
  /financial-data/signatures/{signatureId}:
    get:
      operationId: getSignature
      summary: Get a signature
      tags:
        - Signatures
      security:
        - ApiKeyAuth: []
      description: >-
        Fetches a single signature by id. Returned as a bare `Signature` object
        — this endpoint is not wrapped in the standard `{status, requestId,
        data, errors}` envelope.
      parameters:
        - $ref: '#/components/parameters/DataPlatformRequestId'
        - name: signatureId
          in: path
          required: true
          description: The signature id.
          schema:
            type: string
            example: 665f1a2b3c4d5e6f7a8b9c0d
      responses:
        '200':
          $ref: '#/components/responses/DataPlatformSignature'
        '400':
          $ref: '#/components/responses/DataPlatformBadRequest'
        '401':
          $ref: '#/components/responses/DataPlatformUnauthorized'
        '404':
          $ref: '#/components/responses/DataPlatformNotFound'
        '500':
          $ref: '#/components/responses/DataPlatformInternalError'
        '502':
          $ref: '#/components/responses/DataPlatformBadGateway'
  /financial-data/signatures/{signatureId}/versions:
    post:
      operationId: createSignatureVersion
      summary: Add a signature version
      tags:
        - Signatures
      security:
        - ApiKeyAuth: []
      description: >-
        Creates a new version of an existing signature. Archived signatures
        cannot be versioned (returns 409).
      parameters:
        - $ref: '#/components/parameters/DataPlatformRequestId'
        - name: signatureId
          in: path
          required: true
          description: The signature id.
          schema:
            type: string
            example: 665f1a2b3c4d5e6f7a8b9c0d
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateSignatureRequest'
            example:
              model: gl-accounts
              entityIds:
                - 507f1f77bcf86cd799439011
              customFields:
                - name: costCenter
                  type: string
      responses:
        '200':
          $ref: '#/components/responses/DataPlatformSignatureVersion'
        '400':
          $ref: '#/components/responses/DataPlatformBadRequest'
        '401':
          $ref: '#/components/responses/DataPlatformUnauthorized'
        '404':
          $ref: '#/components/responses/DataPlatformNotFound'
        '409':
          $ref: '#/components/responses/DataPlatformConflict'
        '413':
          $ref: '#/components/responses/DataPlatformBodyTooLarge'
        '422':
          $ref: '#/components/responses/DataPlatformValidationError'
        '500':
          $ref: '#/components/responses/DataPlatformInternalError'
        '502':
          $ref: '#/components/responses/DataPlatformBadGateway'
  /financial-data/gl-accounts:
    post:
      operationId: ingestGlAccounts
      summary: Push GL accounts
      tags:
        - GL Accounts
      security:
        - ApiKeyAuth: []
      description: >-
        Pushes a batch of chart-of-accounts records for the authenticated
        tenant. Pass the `x-signature-id` header to target a registered schema
        version; the accepted `runId` is returned in the 202 response.


        The entire batch is validated before any record is forwarded — a single
        violation rejects the whole request with `422` and a plural `errors[]`
        body (dotted parameter paths, e.g. `records[2].financialStatement`).
      parameters:
        - $ref: '#/components/parameters/DataPlatformSignatureId'
        - $ref: '#/components/parameters/DataPlatformRequestId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GlAccountsIngestRequest'
            example:
              submitMode: UPSERT
              entityIds:
                - 507f1f77bcf86cd799439011
              records:
                - sourceAccountId: '1000'
                  accountNumber: '1000'
                  accountName: Cash and Cash Equivalents
                  financialStatement: BALANCE_SHEET
                  accountType: ASSET
                  accountBalanceType: DEBIT
      responses:
        '202':
          $ref: '#/components/responses/DataPlatformIngestAccepted'
        '400':
          $ref: '#/components/responses/DataPlatformBadRequest'
        '401':
          $ref: '#/components/responses/DataPlatformUnauthorized'
        '403':
          $ref: '#/components/responses/DataPlatformForbidden'
        '413':
          $ref: '#/components/responses/DataPlatformBodyTooLarge'
        '422':
          $ref: '#/components/responses/DataPlatformValidationError'
        '502':
          $ref: '#/components/responses/DataPlatformBadGateway'
  /financial-data/gl-balances:
    post:
      operationId: ingestGlBalances
      summary: Push GL balances
      tags:
        - GL Balances
      security:
        - ApiKeyAuth: []
      description: >-
        Pushes a batch of trial-balance records for a given period. `period` is
        required and scopes all records in the request. Pass the
        `x-signature-id` header to target a registered schema version.
      parameters:
        - $ref: '#/components/parameters/DataPlatformSignatureId'
        - $ref: '#/components/parameters/DataPlatformRequestId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GlBalancesIngestRequest'
            example:
              submitMode: APPEND
              period: 2024-01
              entityIds:
                - 507f1f77bcf86cd799439011
              records:
                - balancePeriod: 2024-01
                  amount: 125000
                  sourceAccountId: '1000'
                  trialBalanceType: CONSOLIDATED
                  currency: USD
      responses:
        '202':
          $ref: '#/components/responses/DataPlatformIngestAccepted'
        '400':
          $ref: '#/components/responses/DataPlatformBadRequest'
        '401':
          $ref: '#/components/responses/DataPlatformUnauthorized'
        '403':
          $ref: '#/components/responses/DataPlatformForbidden'
        '413':
          $ref: '#/components/responses/DataPlatformBodyTooLarge'
        '422':
          $ref: '#/components/responses/DataPlatformValidationError'
        '502':
          $ref: '#/components/responses/DataPlatformBadGateway'
  /financial-data/gl-transactions:
    post:
      operationId: ingestGlTransactions
      summary: Push GL transactions
      tags:
        - GL Transactions
      security:
        - ApiKeyAuth: []
      description: >-
        Pushes a batch of general-ledger transaction lines for a given period.
        `period` is required and scopes all records in the request. Pass the
        `x-signature-id` header to target a registered schema version.


        **APPEND and REPLACE only** — UPSERT is not supported for this model.
      parameters:
        - $ref: '#/components/parameters/DataPlatformSignatureId'
        - $ref: '#/components/parameters/DataPlatformRequestId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GlTransactionsIngestRequest'
            example:
              submitMode: APPEND
              period: 2024-01
              entityIds:
                - 507f1f77bcf86cd799439011
              records:
                - uniqueTransactionId: TXN-001
                  transactionDate: '2024-01-15'
                  postingDate: '2024-01-15'
                  transactionAmountLocal: 5000
                  transactionCurrencyLocal: USD
                  transactionAmountFunctional: 5000
                  transactionCurrencyFunctional: USD
                  sourceAccountId: '1000'
      responses:
        '202':
          $ref: '#/components/responses/DataPlatformIngestAccepted'
        '400':
          $ref: '#/components/responses/DataPlatformBadRequest'
        '401':
          $ref: '#/components/responses/DataPlatformUnauthorized'
        '403':
          $ref: '#/components/responses/DataPlatformForbidden'
        '413':
          $ref: '#/components/responses/DataPlatformBodyTooLarge'
        '422':
          $ref: '#/components/responses/DataPlatformValidationError'
        '502':
          $ref: '#/components/responses/DataPlatformBadGateway'
  /financial-data/fx-rates:
    post:
      operationId: ingestFxRates
      summary: Push FX rates
      tags:
        - FX Rates
      security:
        - ApiKeyAuth: []
      description: >-
        Pushes a batch of exchange-rate records. Unlike the GL models, FX rates
        are not period- or entity-scoped — the body contains only `submitMode`
        and `records`. Pass the `x-signature-id` header to target a registered
        schema version.
      parameters:
        - $ref: '#/components/parameters/DataPlatformSignatureId'
        - $ref: '#/components/parameters/DataPlatformRequestId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FxRatesIngestRequest'
            example:
              submitMode: UPSERT
              records:
                - sourceCurrencyId: USD
                  targetCurrencyId: EUR
                  rateType: AVERAGE
                  rateValue: 0.92
                  effectiveDatetime: '2024-01-31T00:00:00Z'
      responses:
        '202':
          $ref: '#/components/responses/DataPlatformIngestAccepted'
        '400':
          $ref: '#/components/responses/DataPlatformBadRequest'
        '401':
          $ref: '#/components/responses/DataPlatformUnauthorized'
        '403':
          $ref: '#/components/responses/DataPlatformForbidden'
        '413':
          $ref: '#/components/responses/DataPlatformBodyTooLarge'
        '422':
          $ref: '#/components/responses/DataPlatformValidationError'
        '502':
          $ref: '#/components/responses/DataPlatformBadGateway'
  /financial-data/companies:
    post:
      operationId: ingestCompanies
      summary: Push companies
      tags:
        - Companies
      security:
        - ApiKeyAuth: []
      description: >-
        Pushes a batch of company master-data records for the authenticated
        tenant. Not period- or entity-scoped — the body contains only
        `submitMode` and `records`. Pass the `x-signature-id` header to target a
        registered schema version.
      parameters:
        - $ref: '#/components/parameters/DataPlatformSignatureId'
        - $ref: '#/components/parameters/DataPlatformRequestId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CompaniesIngestRequest'
            example:
              submitMode: UPSERT
              records:
                - sourceId: CO-1
                  companyName: Acme US
                  active: true
                  country: US
      responses:
        '202':
          $ref: '#/components/responses/DataPlatformIngestAccepted'
        '400':
          $ref: '#/components/responses/DataPlatformBadRequest'
        '401':
          $ref: '#/components/responses/DataPlatformUnauthorized'
        '403':
          $ref: '#/components/responses/DataPlatformForbidden'
        '413':
          $ref: '#/components/responses/DataPlatformBodyTooLarge'
        '422':
          $ref: '#/components/responses/DataPlatformValidationError'
        '502':
          $ref: '#/components/responses/DataPlatformBadGateway'
  /financial-data/sl-transactions:
    post:
      operationId: ingestSlTransactions
      summary: Push subledger (SL) transactions
      tags:
        - SL Transactions
      security:
        - ApiKeyAuth: []
      description: >-
        Pushes a batch of subledger transaction lines for a given period.
        `period` is required and scopes all records. Entity scoping is
        **per-record** — each record carries its own `entityAssociation` (there
        is no batch-level `entityIds`). Pass the `x-signature-id` header to
        target a registered schema version.


        When `submitMode` is `REPLACE`, each record's `accountType` is required.
      parameters:
        - $ref: '#/components/parameters/DataPlatformSignatureId'
        - $ref: '#/components/parameters/DataPlatformRequestId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SlTransactionsIngestRequest'
            example:
              submitMode: APPEND
              period: 2024-01
              records:
                - transactionId: SLT-001
                  accountType: ACCOUNTS_RECEIVABLE
                  transactionDate: '2024-01-15'
                  postingDate: '2024-01-15'
                  localAmount: 5000
                  localCurrency: USD
                  functionalAmount: 5000
                  functionalCurrency: USD
                  entityAssociation: 507f1f77bcf86cd799439011
      responses:
        '202':
          $ref: '#/components/responses/DataPlatformIngestAccepted'
        '400':
          $ref: '#/components/responses/DataPlatformBadRequest'
        '401':
          $ref: '#/components/responses/DataPlatformUnauthorized'
        '403':
          $ref: '#/components/responses/DataPlatformForbidden'
        '413':
          $ref: '#/components/responses/DataPlatformBodyTooLarge'
        '422':
          $ref: '#/components/responses/DataPlatformValidationError'
        '502':
          $ref: '#/components/responses/DataPlatformBadGateway'
  /financial-data/status/{requestId}:
    get:
      operationId: getIngestStatus
      summary: Get ingest request status
      tags:
        - Ingest Status
      security:
        - ApiKeyAuth: []
      description: >-
        Returns the current file-journey lifecycle status for a `requestId` —
        the `runId` returned by an ingest 202 response. The tenant used for the
        lookup is always the caller's tenant, never a client-supplied value.
      parameters:
        - $ref: '#/components/parameters/DataPlatformRequestId'
        - name: requestId
          in: path
          required: true
          description: The `runId` returned by the ingest endpoint (202 response).
          schema:
            type: string
            format: uuid
      responses:
        '200':
          $ref: '#/components/responses/DataPlatformIngestStatus'
        '401':
          $ref: '#/components/responses/DataPlatformUnauthorized'
        '404':
          $ref: '#/components/responses/DataPlatformNotFound'
        '502':
          $ref: '#/components/responses/DataPlatformBadGateway'
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        API key for server-to-server access. Use `x-api-key: sk_live_...`
        header.
  parameters:
    DataPlatformSignatureId:
      name: x-signature-id
      in: header
      required: true
      schema:
        type: string
        example: 665f1a2b3c4d5e6f7a8b9c0d
      description: >-
        Identifies the registered signature (schema version) this push targets.
        Required on every ingest request. Echoed back in the 202 response as
        `signatureId`.
    DataPlatformRequestId:
      name: x-request-id
      in: header
      required: true
      schema:
        type: string
        format: uuid
        example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
      description: >-
        Client-supplied correlation id (UUID). Required on every request. Echoed
        back in the `X-Request-Id` response header and the response envelope's
        `requestId`.
  schemas:
    GlAccountsIngestRequest:
      type: object
      required:
        - submitMode
        - records
      properties:
        entityIds:
          type: array
          items:
            type: string
          description: >-
            Entity IDs scoping this batch. Conditionally required: mandatory
            (non-empty, and every id within the signature's configured entity
            set) when the signature is scoped to one or more entities; must be
            omitted or empty when the signature is unscoped. A violation is
            rejected with 422. Each id is a FloQast entity id in MongoDB
            ObjectId format (a 24-character hexadecimal string).
          example:
            - 507f1f77bcf86cd799439011
        submitMode:
          $ref: '#/components/schemas/SubmitModeAllThree'
        records:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/GlAccountRecord'
    GlBalancesIngestRequest:
      type: object
      required:
        - period
        - submitMode
        - records
      properties:
        period:
          type: string
          description: Period these balances belong to (YYYY-MM or YYYY-MM-DD).
          example: 2024-01
        entityIds:
          type: array
          items:
            type: string
          description: >-
            Entity IDs scoping this batch. Conditionally required: mandatory
            (non-empty, and every id within the signature's configured entity
            set) when the signature is scoped to one or more entities; must be
            omitted or empty when the signature is unscoped. A violation is
            rejected with 422. Each id is a FloQast entity id in MongoDB
            ObjectId format (a 24-character hexadecimal string).
          example:
            - 507f1f77bcf86cd799439011
        submitMode:
          $ref: '#/components/schemas/SubmitModeAllThree'
        records:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/GlBalanceRecord'
    GlTransactionsIngestRequest:
      type: object
      required:
        - period
        - submitMode
        - records
      properties:
        period:
          type: string
          description: Period these transactions belong to (YYYY-MM or YYYY-MM-DD).
          example: 2024-01
        entityIds:
          type: array
          items:
            type: string
          description: >-
            Entity IDs scoping this batch. Conditionally required: mandatory
            (non-empty, and every id within the signature's configured entity
            set) when the signature is scoped to one or more entities; must be
            omitted or empty when the signature is unscoped. A violation is
            rejected with 422. Each id is a FloQast entity id in MongoDB
            ObjectId format (a 24-character hexadecimal string).
          example:
            - 507f1f77bcf86cd799439011
        submitMode:
          $ref: '#/components/schemas/SubmitModeAppendReplace'
        records:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/GlTransactionRecord'
    FxRatesIngestRequest:
      type: object
      required:
        - submitMode
        - records
      properties:
        submitMode:
          $ref: '#/components/schemas/SubmitModeAllThree'
        records:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/FxRateRecord'
    CompaniesIngestRequest:
      type: object
      required:
        - submitMode
        - records
      properties:
        submitMode:
          $ref: '#/components/schemas/SubmitModeAllThree'
        records:
          type: array
          minItems: 1
          description: Company master-data records for the tenant.
          items:
            $ref: '#/components/schemas/CompanyRecord'
    SlTransactionsIngestRequest:
      type: object
      required:
        - period
        - submitMode
        - records
      properties:
        period:
          type: string
          description: Accounting period (YYYY-MM). Required; scopes all records.
          example: 2024-01
        submitMode:
          $ref: '#/components/schemas/SubmitModeAllThree'
        records:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/SlTransactionRecord'
    SlTransactionRecord:
      type: object
      required:
        - transactionId
        - transactionDate
        - postingDate
        - localAmount
        - localCurrency
        - functionalAmount
        - functionalCurrency
        - entityAssociation
      properties:
        transactionId:
          type: string
          example: SLT-001
        accountType:
          type: string
          enum:
            - ACCOUNTS_RECEIVABLE
            - ACCOUNTS_PAYABLE
            - FIXED_ASSETS
            - ACCUMULATED_DEPRECIATION
            - INVENTORY
            - CASH
            - SALES
            - PURCHASE
            - PAYROLL
            - INTERCOMPANY
            - LEASES
            - OTHER
          description: >-
            Subledger account type. Conditionally required — mandatory when
            `submitMode` is REPLACE; enum-validated whenever provided.
          example: ACCOUNTS_RECEIVABLE
        transactionDate:
          type: string
          example: '2024-01-15'
        postingDate:
          type: string
          example: '2024-01-15'
        localAmount:
          type: number
          format: double
          example: 5000
        localCurrency:
          type: string
          example: USD
        functionalAmount:
          type: number
          format: double
          example: 5000
        functionalCurrency:
          type: string
          example: USD
        entityAssociation:
          type: string
          description: >-
            Entity this record is associated with (per-record entity scoping). A
            FloQast entity id in MongoDB ObjectId format (a 24-character
            hexadecimal string).
          example: 507f1f77bcf86cd799439011
        description:
          type: string
        effectiveStartDate:
          type: string
        effectiveEndDate:
          type: string
        dimensions:
          type: object
          additionalProperties: true
        customFields:
          type: object
          additionalProperties: true
    GlAccountRecord:
      type: object
      required:
        - sourceAccountId
        - accountNumber
        - accountName
        - financialStatement
      properties:
        sourceAccountId:
          type: string
          example: '1000'
        accountNumber:
          type: string
          example: '1000'
        accountName:
          type: string
          example: Cash and Cash Equivalents
        financialStatement:
          type: string
          enum:
            - BALANCE_SHEET
            - INCOME_STATEMENT
            - OTHER_COMPREHENSIVE_INCOME
          example: BALANCE_SHEET
        accountType:
          type: string
          enum:
            - ASSET
            - LIABILITY
            - EQUITY
            - REVENUE
            - EXPENSE
          example: ASSET
        accountBalanceType:
          type: string
          enum:
            - DEBIT
            - CREDIT
            - DOES_NOT_APPLY
          example: DEBIT
        isActive:
          type: boolean
          example: true
        isIntercompany:
          type: boolean
          example: false
        accountCurrency:
          type: string
          example: USD
        exchangeRateType:
          type: string
          enum:
            - CURRENT
            - AVERAGE
            - HISTORICAL
            - CUSTOM
          example: CURRENT
        sourceCreatedDate:
          type: string
          example: '2023-01-01'
        sourceCreatedBy:
          type: string
          example: admin@example.com
        effectiveStartDate:
          type: string
          example: '2023-01-01'
        customFields:
          type: object
          additionalProperties: true
    GlBalanceRecord:
      type: object
      required:
        - balancePeriod
        - amount
        - sourceAccountId
        - balanceEndDate
      properties:
        balancePeriod:
          type: string
          example: 2024-01
        amount:
          type: number
          format: double
          example: 125000
        sourceAccountId:
          type: string
          example: '1000'
        trialBalanceType:
          type: string
          enum:
            - CONSOLIDATED
            - COMPANY
            - DIMENSIONAL
          example: CONSOLIDATED
        balanceStartDate:
          type: string
          example: '2024-01-01'
        balanceEndDate:
          type: string
          example: '2024-01-31'
        currency:
          type: string
          example: USD
        dimensions:
          type: object
          additionalProperties: true
        customFields:
          type: object
          additionalProperties: true
    GlTransactionRecord:
      type: object
      required:
        - uniqueTransactionId
        - transactionDate
        - postingDate
        - transactionAmountLocal
        - transactionCurrencyLocal
        - transactionAmountFunctional
        - transactionCurrencyFunctional
        - sourceAccountId
      properties:
        uniqueTransactionId:
          type: string
          example: TXN-001
        transactionDate:
          type: string
          example: '2024-01-15'
        postingDate:
          type: string
          example: '2024-01-15'
        transactionAmountLocal:
          type: number
          format: double
          example: 5000
        transactionCurrencyLocal:
          type: string
          example: USD
        transactionAmountFunctional:
          type: number
          format: double
          example: 5000
        transactionCurrencyFunctional:
          type: string
          example: USD
        sourceAccountId:
          type: string
          example: '1000'
        transactionType:
          type: string
          example: JOURNAL
        transactionStatus:
          type: string
          enum:
            - POSTED
            - DRAFT
            - VOIDED
            - REVERSED
          example: POSTED
        isPosted:
          type: boolean
          example: true
        description:
          type: string
          example: Monthly SaaS subscription
        fxRate:
          type: number
          format: double
          example: 1
        journalEntryId:
          type: string
          example: JE-2024-001
        amortizationStartDate:
          type: string
          example: '2024-01-01'
        amortizationEndDate:
          type: string
          example: '2024-12-31'
        amortizationUsefulLifeMonths:
          type: integer
          example: 12
        sourceCreatedDate:
          type: string
          example: '2024-01-15'
        dimensions:
          type: object
          additionalProperties: true
        customFields:
          type: object
          additionalProperties: true
    FxRateRecord:
      type: object
      required:
        - sourceCurrencyId
        - targetCurrencyId
        - rateType
        - rateValue
        - effectiveDatetime
      properties:
        sourceCurrencyId:
          type: string
          example: USD
        targetCurrencyId:
          type: string
          example: EUR
        rateType:
          type: string
          enum:
            - AVERAGE
            - CURRENT
            - HISTORICAL
            - CUSTOM
          example: AVERAGE
        rateValue:
          type: number
          format: double
          example: 0.92
        effectiveDatetime:
          type: string
          example: '2024-01-31T00:00:00Z'
        rateName:
          type: string
          example: January 2024 average
        inverseRateValue:
          type: number
          format: double
          example: 1.087
        endDatetime:
          type: string
          example: '2024-01-31T23:59:59Z'
        customFields:
          type: object
          additionalProperties: true
    CompanyRecord:
      type: object
      required:
        - sourceId
        - companyName
      properties:
        sourceId:
          type: string
          description: Source-system company identifier.
          example: CO-1
        companyName:
          type: string
          description: Company display name.
          example: Acme US
        active:
          type: boolean
          description: Whether the company is active. Optional.
          example: true
        country:
          type: string
          description: Country code. Optional.
          example: US
        legalName:
          type: string
          description: Registered legal name. Optional.
        localCurrency:
          type: string
          description: Local currency code. Optional.
        functionalCurrency:
          type: string
          description: Functional currency code. Optional.
        reportingCurrency:
          type: string
          description: Reporting currency code. Optional.
        stateProvince:
          type: string
          description: State or province. Optional.
        lastModifiedDate:
          type: string
          description: Source last-modified date. Optional.
        customFields:
          type: object
          additionalProperties: true
    SubmitModeAllThree:
      type: string
      enum:
        - APPEND
        - UPSERT
        - REPLACE
      description: >-
        - `APPEND` — add records; do not touch existing data. - `UPSERT` — add
        new records; update matching existing records. - `REPLACE` — replace all
        existing data for the scope with this batch.
      example: UPSERT
    SubmitModeAppendReplace:
      type: string
      enum:
        - APPEND
        - REPLACE
      description: >-
        - `APPEND` — add records; do not touch existing data. - `REPLACE` —
        replace all existing data for the scope with this batch.

        Note: `UPSERT` is not supported for GL transactions.
      example: APPEND
    SignatureField:
      type: object
      required:
        - name
        - type
      properties:
        name:
          type: string
          description: Custom field name (letters only, unique within the signature).
          example: costCenter
        type:
          type: string
          enum:
            - string
            - number
            - integer
            - boolean
            - date
            - datetime
          description: Flex data type for the custom field.
          example: string
    SignatureModel:
      type: string
      description: >-
        Ingest model this signature targets. Must be one of the six supported
        model identifiers.
      enum:
        - gl-accounts
        - gl-balances
        - gl-transactions
        - fx-rates
        - companies
        - sl-transactions
      x-enumDescriptions:
        gl-accounts: >-
          GL Accounts — APPEND adds records, UPSERT adds or updates matching
          records, REPLACE overwrites the entire dataset.
        gl-balances: >-
          GL Balances — period-scoped; APPEND adds records, UPSERT adds or
          updates matching records, REPLACE overwrites only the submitted
          `period`.
        gl-transactions: >-
          GL Transactions — period-scoped; APPEND adds records, REPLACE
          overwrites only the submitted `period` (UPSERT not supported).
        fx-rates: >-
          FX Rates — APPEND adds records, UPSERT adds or updates matching
          records, REPLACE overwrites the entire dataset.
        companies: >-
          Companies — APPEND adds records, UPSERT adds or updates matching
          records, REPLACE overwrites the entire dataset.
        sl-transactions: >-
          Subledger Transactions — period-scoped; APPEND adds records, UPSERT
          adds or updates matching records, REPLACE overwrites only the
          submitted `period`.
      example: gl-accounts
    Signature:
      type: object
      required:
        - id
        - name
        - description
        - model
        - status
        - customFields
        - createdAt
        - updatedAt
      properties:
        id:
          type: string
          example: 665f1a2b3c4d5e6f7a8b9c0d
        name:
          type: string
          example: Primary GL Accounts signature
        description:
          type: string
          example: Chart-of-accounts schema v2
        model:
          $ref: '#/components/schemas/SignatureModel'
        entityIds:
          type: array
          items:
            type: string
          description: >-
            Entities this signature is scoped to (omitted when unscoped). Each
            id is a FloQast entity id in MongoDB ObjectId format (a 24-character
            hexadecimal string).
          example:
            - 507f1f77bcf86cd799439011
        status:
          type: string
          description: Signature status (e.g. `active`, `archived`).
          example: active
        customFields:
          type: array
          items:
            $ref: '#/components/schemas/SignatureField'
        createdAt:
          type: string
          description: Creation timestamp (as returned by the metadata service).
          example: '2024-01-31T00:00:00Z'
        updatedAt:
          type: string
          description: Last-update timestamp (as returned by the metadata service).
          example: '2024-01-31T00:00:00Z'
    CreateSignatureRequest:
      type: object
      required:
        - name
        - model
      properties:
        name:
          type: string
          description: Human-readable signature name (unique per connector).
          example: Primary GL Accounts signature
        description:
          type: string
          example: Chart-of-accounts schema v2
        model:
          $ref: '#/components/schemas/SignatureModel'
        entityIds:
          type: array
          items:
            type: string
          description: >-
            Entities this signature is scoped to (omit or leave empty when
            unscoped). Each id is a FloQast entity id in MongoDB ObjectId format
            (a 24-character hexadecimal string).
          example:
            - 507f1f77bcf86cd799439011
        customFields:
          type: array
          items:
            $ref: '#/components/schemas/SignatureField'
    UpdateSignatureRequest:
      type: object
      required:
        - model
      properties:
        model:
          $ref: '#/components/schemas/SignatureModel'
        entityIds:
          type: array
          items:
            type: string
          description: >-
            Entities this signature version is scoped to (omit or leave empty
            when unscoped). Each id is a FloQast entity id in MongoDB ObjectId
            format (a 24-character hexadecimal string).
          example:
            - 507f1f77bcf86cd799439011
        customFields:
          type: array
          items:
            $ref: '#/components/schemas/SignatureField'
    UpdateSignatureResult:
      type: object
      required:
        - id
        - version
        - status
        - createdAt
        - updatedAt
      properties:
        id:
          type: string
          example: 665f1a2b3c4d5e6f7a8b9c0d
        version:
          type: integer
          description: The new version number.
          example: 2
        status:
          type: string
          example: active
        createdAt:
          type: string
          example: '2024-01-31T00:00:00Z'
        updatedAt:
          type: string
          example: '2024-01-31T00:00:00Z'
    error:
      type: object
      required:
        - title
        - status
        - code
        - detail
      additionalProperties: false
      description: >-
        A single error (RFC 9457-style). The per-request correlation id is
        carried at the envelope level as `requestId` (matching the
        `X-Request-Id` response header), not inside each error object.
      properties:
        code:
          type: string
          description: >-
            Machine-readable error identifier (e.g. `invalid_json`,
            `parameter_missing`).
          example: invalid_json
        detail:
          type: string
          description: Human-readable explanation of this specific error.
          example: request body is not valid JSON
        param:
          type: string
          description: >-
            JSON path of the offending field for validation errors (e.g.
            `records[0].financialStatement`).
        status:
          type: integer
          description: HTTP status code.
          example: 400
        title:
          type: string
          description: Canonical HTTP reason phrase for the status.
          example: Bad Request
        type:
          type: string
          description: URI identifying the error class.
        instance:
          type: string
          description: >-
            URI reference to the specific occurrence (RFC 9457; defaults to
            `about:blank`).
    DataPlatformFailureEnvelope:
      type: object
      required:
        - status
        - requestId
        - errors
      description: Standard failure envelope returned on 400 / 401 / 404 / 413 / 422 / 502.
      properties:
        status:
          type: string
          enum:
            - failed
          example: failed
        requestId:
          type: string
          description: >-
            Per-request correlation id (matches the `X-Request-Id` header);
            present on every response.
          example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
        data:
          type: object
          nullable: true
          description: Null on failure.
        errors:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/error'
    IngestStatus:
      type: object
      required:
        - eventId
        - status
      properties:
        eventId:
          type: string
          format: uuid
          description: The `runId` returned by the ingest endpoint (202 response).
          example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
        status:
          type: string
          description: Current lifecycle status.
          enum:
            - RECEIVED
            - IN_PROGRESS
            - SUCCESS
            - FAILED
          example: IN_PROGRESS
        timestamp:
          type: integer
          format: int64
          description: Unix epoch milliseconds of the latest status update.
          example: 1719849600000
        errorDetails:
          type: object
          nullable: true
          description: Error summary; populated when the run failed, null otherwise.
          allOf:
            - $ref: '#/components/schemas/StatusErrorDetails'
    StatusErrorDetails:
      type: object
      properties:
        code:
          type: string
          example: validation_failed
        message:
          type: string
          example: 3 records failed referential-integrity checks
  headers:
    RequestId:
      description: Unique identifier for this request, used for tracing and support.
      schema:
        type: string
        example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
  responses:
    DataPlatformIngestAccepted:
      description: >-
        Batch accepted and forwarded to the Direct-Connect Gateway. Record-level
        validation (referential integrity, business rules) occurs asynchronously
        in the data pipeline. Poll `GET /financial-data/status/{requestId}` with
        the returned `runId` to track lifecycle status.
      headers:
        x-request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            type: object
            required:
              - status
              - requestId
              - data
              - errors
            properties:
              status:
                type: string
                enum:
                  - accepted
                example: accepted
              requestId:
                type: string
                description: >-
                  Per-request correlation id (matches the `X-Request-Id`
                  header).
                example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
              data:
                type: object
                required:
                  - runId
                properties:
                  runId:
                    type: string
                    format: uuid
                    description: >-
                      Unique identifier for this ingest request. Use with `GET
                      /financial-data/status/{requestId}` to poll lifecycle
                      status.
                    example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                  signatureId:
                    type: string
                    description: Echoed from the `x-signature-id` request header.
                    example: 665f1a2b3c4d5e6f7a8b9c0d
                  submitMode:
                    $ref: '#/components/schemas/SubmitModeAllThree'
                  recordsReceived:
                    type: integer
                    description: Number of records accepted.
                    example: 128
              errors:
                type: array
                description: Always empty ([]) on success.
                items:
                  $ref: '#/components/schemas/error'
    DataPlatformIngestStatus:
      description: Current lifecycle status of the ingest request.
      headers:
        x-request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            type: object
            required:
              - status
              - requestId
              - data
              - errors
            properties:
              status:
                type: string
                enum:
                  - ok
                example: ok
              requestId:
                type: string
                example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
              data:
                $ref: '#/components/schemas/IngestStatus'
              errors:
                type: array
                items:
                  $ref: '#/components/schemas/error'
    DataPlatformBadRequest:
      description: Request body is missing, not valid JSON, or cannot be read.
      headers:
        x-request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/DataPlatformFailureEnvelope'
          example:
            status: failed
            requestId: a1b2c3d4-e5f6-7890-abcd-ef1234567890
            data: null
            errors:
              - code: invalid_json
                detail: request body is not valid JSON
                status: 400
                title: Bad Request
    DataPlatformUnauthorized:
      description: >-
        Missing or invalid API key. Ensure the `x-api-key` header is present and
        valid.
      headers:
        x-request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/DataPlatformFailureEnvelope'
    DataPlatformForbidden:
      description: >-
        The `x-signature-id` is invalid or inactive, the signature does not
        match the target model, or the caller lacks the required scope.
      headers:
        x-request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/DataPlatformFailureEnvelope'
    DataPlatformNotFound:
      description: No ingest request was found for the given `requestId`.
      headers:
        x-request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/DataPlatformFailureEnvelope'
    DataPlatformBodyTooLarge:
      description: Request body exceeds the maximum allowed size.
      headers:
        x-request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/DataPlatformFailureEnvelope'
          example:
            status: failed
            requestId: a1b2c3d4-e5f6-7890-abcd-ef1234567890
            data: null
            errors:
              - code: body_too_large
                detail: request body exceeds the maximum allowed size
                status: 413
                title: Payload Too Large
    DataPlatformValidationError:
      description: >-
        One or more fields failed shape validation. The entire batch is rejected
        — no records are ingested. Fix all violations and resubmit.
      headers:
        x-request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/DataPlatformFailureEnvelope'
          example:
            status: failed
            requestId: a1b2c3d4-e5f6-7890-abcd-ef1234567890
            data: null
            errors:
              - code: parameter_invalid
                detail: >-
                  must be one of: BALANCE_SHEET, INCOME_STATEMENT,
                  OTHER_COMPREHENSIVE_INCOME
                param: records[0].financialStatement
                status: 422
                title: Unprocessable Entity
    DataPlatformBadGateway:
      description: >-
        Upstream service temporarily unavailable. Safe to retry with exponential
        backoff.
      headers:
        x-request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/DataPlatformFailureEnvelope'
          example:
            status: failed
            requestId: a1b2c3d4-e5f6-7890-abcd-ef1234567890
            data: null
            errors:
              - code: upstream_unavailable
                detail: could not accept request, please retry
                status: 502
                title: Bad Gateway
    DataPlatformConflict:
      description: >-
        The request conflicts with existing state — e.g. the signature name is
        already in use, or an entity-id conflict, or the signature is archived.
      headers:
        x-request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/DataPlatformFailureEnvelope'
    DataPlatformInternalError:
      description: Unexpected server error.
      headers:
        x-request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/DataPlatformFailureEnvelope'
    DataPlatformSignatureCreated:
      description: Signature created.
      headers:
        x-request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            type: object
            required:
              - status
              - requestId
              - data
              - errors
            properties:
              status:
                type: string
                enum:
                  - ok
                example: ok
              requestId:
                type: string
                example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
              data:
                $ref: '#/components/schemas/Signature'
              errors:
                type: array
                items:
                  $ref: '#/components/schemas/error'
    DataPlatformSignature:
      description: >-
        The requested signature, returned as a bare object (this endpoint is not
        wrapped in the standard envelope).
      headers:
        x-request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Signature'
    DataPlatformSignatureVersion:
      description: New signature version created.
      headers:
        x-request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            type: object
            required:
              - status
              - requestId
              - data
              - errors
            properties:
              status:
                type: string
                enum:
                  - ok
                example: ok
              requestId:
                type: string
                example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
              data:
                $ref: '#/components/schemas/UpdateSignatureResult'
              errors:
                type: array
                items:
                  $ref: '#/components/schemas/error'
