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

# Opt in to matching

> Has QuBe Sync build the connection's name index now, so it's ready before your first match, and tells you when it is. QuBe Sync reads the names in the connection's lists from QuickBooks itself, a step at a time, as the Web Connector checks in, and your own requests always go first. That takes a few Web Connector sessions, more on a large company file.

While it builds the answer is `202`. Pass a `webhook_url` to be sent `name_index.ready` once it's in, or `name_index.failed` if the build gives up (see the callback). Calling this again while it builds replaces the `webhook_url`, and starts nothing more. On an index that's already `ready` the answer is `200`, and nothing is sent. So it's safe to repeat, and takes no `Idempotency-Key`.

Only `realtime` and `simulated` connections can have an index (422 `matching_requires_realtime`). An index is kept current while it was used in the last 7 days, and deleted after 30 days unused: a match counts as a use, and so does this.



## OpenAPI

````yaml /api-reference/v2/openapi.json post /connections/{connection_id}/name-index
openapi: 3.1.0
info:
  contact:
    email: support@qubesync.com
  description: >
    A single generic operation surface for every curated qbXML request QuBe Sync
    supports, driven directly off the qbXML schema -- see the [MCP
    server](/mcp-server) to explore available operations interactively.


    **Every endpoint queues a request and returns it immediately (`201`, a
    `QueuedRequest`).** QuickBooks Desktop is reached through the customer's Web
    Connector, which polls QuBe Sync, so the answer arrives seconds to minutes
    later. **Pass a `webhook_url` with every request**: when QuickBooks has
    answered, QuBe Sync POSTs the same document to it -- `state` set,
    `response_json` filled in -- signed with `X-QUBE-Signature` (see the
    Webhooks guide). `response_json` is the `{status, data}` envelope documented
    on each operation: `status: "success"` with `data` derived from the qbXML
    `*Ret` (and `warning`, QuickBooks' code and message, when it carried the
    request out but warned about it), or `status: "error"` with QuickBooks' own
    status code and message -- a QuickBooks business error is a *successful*
    HTTP round trip. `links.self` returns the request on demand (for a
    dashboard, a retry, a script); it is not the integration path. Send an
    `Idempotency-Key` header with each request so a call whose answer you never
    got can be sent again without queueing it twice.


    Authentication is HTTP Basic with your app's API key as the username and a
    blank password. Connections themselves (creating one, onboarding, its QWC
    file and password) are the `/connections` endpoints; every QuickBooks
    operation is scoped to one of them.
  title: QuBe Sync API (v2)
  version: 2.0.0
servers:
  - description: v2 API
    url: https://qubesync.com/api/v2
  - description: Local development server
    url: https://dev.qubesync.com/api/v2
security:
  - apiKey: []
tags:
  - description: >-
      Creating and managing the connection (a customer's QuickBooks company
      file) that every request below is queued against. See the Onboarding
      guide.
    name: Connections
  - description: >-
      Queueing qbXML you wrote yourself, listing the requests queued on a
      connection, and discarding one the app no longer wants. A `webhook_url` on
      each request is the integration path (see the Webhooks guide): the listing
      is for a dashboard, a script, or catching up after downtime.
    name: Queued Requests
  - description: >-
      Finding the record in a customer's company file that a name means, even
      written differently: ranked matches from QuBe Sync's index of the file's
      names, on realtime and simulated connections. See the Matching guide.
    name: Matching
  - description: >-
      Endpoints for publishing workflow definitions, starting runs, and
      answering a run that is waiting on a decision from your app. A workflow is
      one JSON statechart document; see the schema at
      /api/v2/workflows/schema.json.
    name: Workflows
  - name: Account Tax Line Infos
  - name: Accounts
  - name: Aging Reports
  - name: Alerts
  - name: Ar Refund Credit Cards
  - name: Bar Codes
  - name: Bill Payment Checks
  - name: Bill Payment Credit Cards
  - name: Bill To Pays
  - name: Billing Rates
  - name: Bills
  - name: Budget Summary Reports
  - name: Build Assemblies
  - name: Charges
  - name: Checks
  - name: Classes
  - name: Cleared Statuses
  - name: Companies
  - name: Company Activities
  - name: Credit Card Charges
  - name: Credit Card Credits
  - name: Credit Memos
  - name: Currencies
  - name: Custom Detail Reports
  - name: Custom Summary Reports
  - name: Customer Msgs
  - name: Customer Types
  - name: Customers
  - name: Data Event Recovery Infos
  - name: Data Ext Defs
  - name: Data Exts
  - name: Date Driven Terms
  - name: Deposits
  - name: Employee Defaults
  - name: Employees
  - name: Entities
  - name: Estimates
  - name: Form1099 Category Account Mappings
  - name: General Detail Reports
  - name: General Summary Reports
  - name: Hosts
  - name: Inventory Adjustments
  - name: Inventory Sites
  - name: Invoices
  - name: Item Assemblies Can Builds
  - name: Item Discounts
  - name: Item Fixed Assets
  - name: Item Groups
  - name: Item Inventories
  - name: Item Inventory Assemblies
  - name: Item Non Inventories
  - name: Item Other Charges
  - name: Item Payments
  - name: Item Receipts
  - name: Item Sales Tax Groups
  - name: Item Sales Taxes
  - name: Item Services
  - name: Item Sites
  - name: Item Subtotals
  - name: Items
  - name: Job Reports
  - name: Job Types
  - name: Journal Entries
  - name: Leads
  - name: List Deleteds
  - name: List Displays
  - name: List Merge
  - name: Lists
  - name: Other Names
  - name: Paychecks
  - name: Payment Methods
  - name: Payments
  - name: Payroll Detail Reports
  - name: Payroll Item Additions
  - name: Payroll Item Company Contributions
  - name: Payroll Item Deductions
  - name: Payroll Item Direct Deposits
  - name: Payroll Item Non Wages
  - name: Payroll Item Taxes
  - name: Payroll Item Wages
  - name: Payroll Item Workers Compensations
  - name: Payroll Items
  - name: Payroll Last Periods
  - name: Payroll Liability Adjustments
  - name: Payroll Liability Checks
  - name: Payroll Prior Payments
  - name: Payroll Summary Reports
  - name: Payroll Year To Date Adjustments
  - name: Preferences
  - name: Price Levels
  - name: Purchase Orders
  - name: Qb Command Exec
  - name: Receive Payment To Deposits
  - name: Receive Payments
  - name: Sales Orders
  - name: Sales Receipts
  - name: Sales Reps
  - name: Sales Tax Codes
  - name: Sales Tax Payables
  - name: Sales Tax Payment Checks
  - name: Sales Tax Return Lines
  - name: Sales Tax Returns
  - name: Ship Methods
  - name: Special Accounts
  - name: Special Items
  - name: Standard Terms
  - name: Templates
  - name: Terms
  - name: Time Reports
  - name: Time Trackings
  - name: To Dos
  - name: Transactions
  - name: Transfer Inventories
  - name: Transfers
  - name: Txn Deleteds
  - name: Txn Displays
  - name: Txn Void
  - name: Txns
  - name: Unit Of Measure Sets
  - name: Vehicle Mileages
  - name: Vehicles
  - name: Vendor Credits
  - name: Vendor Types
  - name: Vendors
  - name: Workers Comp Codes
paths:
  /connections/{connection_id}/name-index:
    post:
      tags:
        - Matching
      summary: Opt in to matching
      description: >-
        Has QuBe Sync build the connection's name index now, so it's ready
        before your first match, and tells you when it is. QuBe Sync reads the
        names in the connection's lists from QuickBooks itself, a step at a
        time, as the Web Connector checks in, and your own requests always go
        first. That takes a few Web Connector sessions, more on a large company
        file.


        While it builds the answer is `202`. Pass a `webhook_url` to be sent
        `name_index.ready` once it's in, or `name_index.failed` if the build
        gives up (see the callback). Calling this again while it builds replaces
        the `webhook_url`, and starts nothing more. On an index that's already
        `ready` the answer is `200`, and nothing is sent. So it's safe to
        repeat, and takes no `Idempotency-Key`.


        Only `realtime` and `simulated` connections can have an index (422
        `matching_requires_realtime`). An index is kept current while it was
        used in the last 7 days, and deleted after 30 days unused: a match
        counts as a use, and so does this.
      operationId: buildNameIndex
      parameters:
        - description: The connection to act on.
          in: path
          name: connection_id
          required: true
          schema:
            format: uuid
            type: string
      requestBody:
        content:
          application/json:
            example:
              webhook_url: https://your-app.example/webhooks/qube
            schema:
              additionalProperties: false
              properties:
                webhook_url:
                  description: >-
                    Where to send `name_index.ready` or `name_index.failed` when
                    the build ends. It must be an absolute http or https URL. It
                    may not contain a username or password, and in production it
                    may not point at localhost or a private, loopback or
                    link-local address. A `qube listen` URL must be one of this
                    app's.
                  example: https://your-app.example/webhooks/qube
                  format: uri
                  maxLength: 2048
                  type: string
              type: object
        required: false
      responses:
        '200':
          content:
            application/json:
              example:
                name_index:
                  as_of: '2026-10-11T14:02:10Z'
                  records: 1240
                  state: ready
              schema:
                properties:
                  name_index:
                    $ref: '#/components/schemas/NameIndex'
                required:
                  - name_index
                type: object
          description: 'The index is ready: match away. Nothing is sent to `webhook_url`.'
        '202':
          content:
            application/json:
              example:
                name_index:
                  as_of: null
                  records: 0
                  state: building
              schema:
                properties:
                  name_index:
                    $ref: '#/components/schemas/NameIndex'
                required:
                  - name_index
                type: object
          description: >-
            The index is being built: this call started it, or it was already
            under way. `webhook_url`, if you sent one, will be told when it
            ends.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          content:
            application/json:
              examples:
                invalid_webhook_url:
                  summary: A webhook_url webhooks can't go to
                  value:
                    errors:
                      webhook_url:
                        - may not contain a username or password
                matching_requires_realtime:
                  summary: A standard connection
                  value:
                    errors:
                      code: matching_requires_realtime
                      detail: >-
                        Matching needs a realtime or simulated connection, and
                        this one is standard. Upgrade it to realtime from its
                        page in the dashboard; in a sandbox app that costs
                        nothing, since sandbox apps aren't billed. A simulated
                        connection matches against the simulator's company file.
              schema:
                $ref: '#/components/schemas/Error'
          description: >-
            `matching_requires_realtime`: the connection is `standard`, which
            has no name index. Or the body was refused field by field: a
            `webhook_url` that isn't an absolute http or https URL, carries a
            username or password, is longer than 2048 characters, or (in
            production) points at localhost or a private address, or a parameter
            it doesn't take.
      callbacks:
        name_index:
          '{$request.body#/webhook_url}':
            post:
              description: >-
                Sent once, when the build this opt-in waited for ends:
                `name_index.ready` or `name_index.failed`. Signed with
                `X-QUBE-Signature` like every other webhook (see the Webhooks
                guide). It names the connection and where its index stands,
                never a record.
              requestBody:
                content:
                  application/json:
                    schema:
                      $ref: '#/components/schemas/NameIndexWebhookPayload'
                required: true
              responses:
                2XX:
                  description: >-
                    Received. Anything else is retried with backoff for about 8
                    hours; after the last attempt, your organization's owners
                    are emailed.
              summary: The name index is ready, or its build gave up
              method: post
              type: path
            path: '{$request.body#/webhook_url}'
      security:
        - apiKey: []
components:
  schemas:
    NameIndex:
      description: >-
        QuBe Sync's index of the names in this connection's company file, for
        finding records by name (see Match a name): customers, vendors,
        employees and other names, items, accounts, classes, and the other lists
        a transaction names (terms, sales tax codes, payment and ship methods,
        price levels, customer, vendor and job types, sales reps and customer
        messages). Only `realtime` and `simulated` connections can have one, and
        it is built the first time something on the connection needs matching: a
        match, or opting in (`POST /connections/{connection_id}/name-index`).
        QuBe Sync then reads the lists from QuickBooks itself, a step at a time,
        and your requests always go first; those reads never appear among your
        requests and never send a webhook. An index unused for 30 days is
        deleted, and built again the next time it's needed.
      properties:
        as_of:
          description: >-
            When the index last caught up with QuickBooks: changes made in
            QuickBooks since then aren't in it yet. While it's used, it catches
            up after a Web Connector session that brought your requests, at most
            every 5 minutes. `null` unless `ready`.
          format: date-time
          nullable: true
          type: string
        records:
          description: >-
            How many records the index holds; while `building`, how many are in
            so far. `null` when `not_built` or `unavailable`.
          nullable: true
          type: integer
        state:
          description: >-
            `ready`: every list is in. `building`: QuBe Sync is reading the
            lists from QuickBooks, the first time, or again after the connection
            was pointed at another company file, went 90 days without your
            requests, or a build gave up. `not_built`: nothing on the connection
            has needed matching yet, or the index went unused for 30 days and
            was deleted. `unavailable`: the connection is `standard`, which
            can't have one.
          enum:
            - ready
            - building
            - not_built
            - unavailable
          type: string
      required:
        - state
        - as_of
        - records
      type: object
    Error:
      description: >-
        What a refused request answers with. The one key is errors, and its
        shape says what went wrong: a sentence when the endpoint explains the
        refusal in words (a parameter the operation does not take, a key already
        taken, a run that has already ended); an object with detail, and a code
        when there is one, when the request named nothing that exists or may not
        do what it asked (402, 403, 404, and a CLI session's 401), or an answer
        to a run's question was refused (the decisions endpoint's 400, 409 and
        422, which always carry a code to branch on); an object of fields, each
        a list of messages, when a record failed validation and nothing was
        saved; a list of {path, message} problems when a submitted document or
        input fails validation. A request without a usable API key gets a 401
        Basic challenge with the plain-text body Unauthorized, not JSON.
      properties:
        errors:
          oneOf:
            - example: 'unknown parameter: "emial"'
              title: A sentence
              type: string
            - properties:
                code:
                  example: read_only_session
                  type: string
                detail:
                  example: Not Found
                  type: string
              required:
                - detail
              title: Detail and code
              type: object
            - additionalProperties:
                items:
                  type: string
                type: array
              example:
                webhook_url:
                  - may not contain a username or password
              title: Field by field
              type: object
            - items:
                properties:
                  message:
                    example: is required
                    type: string
                  path:
                    example: input.customer
                    type: string
                required:
                  - path
                  - message
                type: object
              title: Located problems
              type: array
      required:
        - errors
      type: object
    NameIndexWebhookPayload:
      description: >-
        The body QuBe Sync POSTs to the `webhook_url` an opt-in gave (`POST
        /connections/{connection_id}/name-index`), signed with
        `X-QUBE-Signature` like every other QuBe Sync webhook, once the build it
        was waiting for ends. It says where the index stands, never what's in
        it.
      example:
        app_id: 98f339a4-32e8-424a-987e-ccaf5bcaa620
        connection_id: 3f9c2a71-5d4e-4b8a-9c1f-7e2d6a5b8c90
        event: name_index.ready
        name_index:
          as_of: '2026-10-11T14:02:10Z'
          records: 1240
          state: ready
        sandbox: true
        timestamp: 1792764130
      properties:
        app_id:
          format: uuid
          type: string
        connection_id:
          format: uuid
          type: string
        event:
          description: >-
            `name_index.ready`: every list is in, and matches are answered.
            `name_index.failed`: the build gave up, after QuickBooks' answers to
            one step were lost three times in a row (the session ended, or the
            Web Connector reported an error). Matching is refused while the
            index is `building`; QuBe Sync starts the build again a day later
            while the connection is matching, or at the next match or opt-in.
          enum:
            - name_index.ready
            - name_index.failed
          type: string
        name_index:
          $ref: '#/components/schemas/NameIndex'
        sandbox:
          type: boolean
        timestamp:
          description: Unix seconds; also the `t=` in the signature header.
          type: integer
      required:
        - event
        - timestamp
        - app_id
        - sandbox
        - connection_id
        - name_index
      type: object
  responses:
    Unauthorized:
      content:
        text/plain:
          example: Unauthorized
          schema:
            type: string
      description: >-
        No usable API key. The key is Basic auth, so the answer is the
        challenge, with the plain-text body Unauthorized rather than JSON.
      headers:
        WWW-Authenticate:
          schema:
            example: Basic realm="Application"
            type: string
    NotFound:
      content:
        application/json:
          example:
            errors:
              detail: Not Found
          schema:
            $ref: '#/components/schemas/Error'
      description: Nothing by that id, or it belongs to another app.
  securitySchemes:
    apiKey:
      description: Use your app's API key as the username, and leave the password blank
      scheme: basic
      type: http

````

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