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

# Poll a dedupe scan or merge job (groups / totals when completed)

> Polls a dedupe job started by `POST /business/contacts/dedupe-scan` or `POST /business/contacts/dedupe-merge`; `kind` says which of the two the id names. `status` moves pending > processing > completed or failed; poll every few seconds until it is terminal. On a completed scan, `scanResult` carries one PAGE of the duplicate groups (`pageNum`/`limit`, default 50 per page, largest groups first; `scanResult.pagination` says how many pages there are — page through once `status` is completed rather than re-fetching every group on every poll). Each group carries its `contactIds` (every member), `matchedValues` (the normalized values it matched on), the `lists` its members live in, a preview of up to 25 member `contacts`, and a `mergePreview` of the contact the group would merge into — its surviving `winnerContactId`, filled fields, and the combined `emails`/`phones` unions (first 10 entries each; `emailCount`/`phoneCount` are the full totals). Each group's `groupId` is what `POST /business/contacts/dedupe-merge` selects by. `totalGroups` counts every group the scan FOUND and can exceed the stored 200 (`truncated` says so); `pagination.totalRecords` counts the stored, pageable groups. On a completed merge, `mergeResult` carries `mergedGroups`, `archivedContacts` and `skippedGroups` (groups that no longer had two live members when the merge ran, or whose members' identities conflict). On `failed`, `error` is `DEDUPE_FAILED` — start a new job. Scan results expire with the job (about 24 hours); export jobs are not served here (poll GET /business/exports/{jobId}). Serves only the token owner's own jobs. Rate limit: 120 requests per minute, 10,000 per day on the contacts bucket, which every /business/contacts endpoint shares.

Errors:
- `404` `JOB_NOT_FOUND` — No dedupe job with that id (it may have expired, belong to another workspace, or be an export job).
- `422` `VALIDATION_FAILED` — jobId is not a 24-hex id.
- `429` `RATE_LIMITED` — More than 120 requests per minute or 10,000 per day on the contacts bucket, which every /business/contacts endpoint shares; retry after Retry-After.

Requires one of the following token scopes: contacts.



## OpenAPI

````yaml /openapi.json get /business/contacts/dedupe-jobs/{jobId}
openapi: 3.1.0
info:
  title: Fuse Business API
  version: 1.0.0
  description: >-
    External API for lists, campaigns, prospect search and contacts.
    Authenticate with your API token as HTTP Basic. All paths are under /api/v1.
servers:
  - url: https://api.tryfuse.ai/api/v1
    description: Production
security:
  - basicAuth: []
tags:
  - name: Lists
  - name: Custom columns
  - name: Smart columns
  - name: Exports
  - name: Campaigns
  - name: Knowledge hubs
  - name: Analytics
  - name: Website intent
  - name: Account
  - name: Prospect search
  - name: Campaign steps
  - name: Scheduled sends
  - name: Campaign templates
  - name: Agents
  - name: Research
  - name: Company search
  - name: Saved searches
  - name: Folders
  - name: Contacts
paths:
  /business/contacts/dedupe-jobs/{jobId}:
    get:
      tags:
        - Contacts
      summary: Poll a dedupe scan or merge job (groups / totals when completed)
      description: >-
        Polls a dedupe job started by `POST /business/contacts/dedupe-scan` or
        `POST /business/contacts/dedupe-merge`; `kind` says which of the two the
        id names. `status` moves pending > processing > completed or failed;
        poll every few seconds until it is terminal. On a completed scan,
        `scanResult` carries one PAGE of the duplicate groups
        (`pageNum`/`limit`, default 50 per page, largest groups first;
        `scanResult.pagination` says how many pages there are — page through
        once `status` is completed rather than re-fetching every group on every
        poll). Each group carries its `contactIds` (every member),
        `matchedValues` (the normalized values it matched on), the `lists` its
        members live in, a preview of up to 25 member `contacts`, and a
        `mergePreview` of the contact the group would merge into — its surviving
        `winnerContactId`, filled fields, and the combined `emails`/`phones`
        unions (first 10 entries each; `emailCount`/`phoneCount` are the full
        totals). Each group's `groupId` is what `POST
        /business/contacts/dedupe-merge` selects by. `totalGroups` counts every
        group the scan FOUND and can exceed the stored 200 (`truncated` says
        so); `pagination.totalRecords` counts the stored, pageable groups. On a
        completed merge, `mergeResult` carries `mergedGroups`,
        `archivedContacts` and `skippedGroups` (groups that no longer had two
        live members when the merge ran, or whose members' identities conflict).
        On `failed`, `error` is `DEDUPE_FAILED` — start a new job. Scan results
        expire with the job (about 24 hours); export jobs are not served here
        (poll GET /business/exports/{jobId}). Serves only the token owner's own
        jobs. Rate limit: 120 requests per minute, 10,000 per day on the
        contacts bucket, which every /business/contacts endpoint shares.


        Errors:

        - `404` `JOB_NOT_FOUND` — No dedupe job with that id (it may have
        expired, belong to another workspace, or be an export job).

        - `422` `VALIDATION_FAILED` — jobId is not a 24-hex id.

        - `429` `RATE_LIMITED` — More than 120 requests per minute or 10,000 per
        day on the contacts bucket, which every /business/contacts endpoint
        shares; retry after Retry-After.


        Requires one of the following token scopes: contacts.
      operationId: getDedupeJob
      parameters:
        - name: jobId
          in: path
          required: true
          description: >-
            24-character hex id of an async job, as returned with the 202 that
            started it (POST /business/lists/{listId}/export).
          schema:
            type: string
            description: >-
              24-character hex id of an async job, as returned with the 202 that
              started it (POST /business/lists/{listId}/export).
        - name: pageNum
          in: query
          required: false
          description: >-
            1-based page number over the scan's stored groups (default 1);
            groups are ordered largest first.
          schema:
            type: integer
            minimum: 1
            default: 1
            description: >-
              1-based page number over the scan's stored groups (default 1);
              groups are ordered largest first.
        - name: limit
          in: query
          required: false
          description: >-
            Page size: how many duplicate groups to return per page (1-200,
            default 50). A scan stores at most 200 groups, so limit=200 returns
            the whole result in one page.
          schema:
            type: integer
            minimum: 1
            maximum: 200
            default: 50
            description: >-
              Page size: how many duplicate groups to return per page (1-200,
              default 50). A scan stores at most 200 groups, so limit=200
              returns the whole result in one page.
      responses:
        '200':
          description: Success
          headers:
            RateLimit-Limit:
              schema:
                type: integer
              description: Requests permitted in the current window.
            RateLimit-Remaining:
              schema:
                type: integer
              description: Requests remaining in the current window.
            RateLimit-Reset:
              schema:
                type: integer
              description: Seconds until the current window resets.
          content:
            application/json:
              schema:
                type: object
                required:
                  - dedupeJob
                properties:
                  dedupeJob:
                    type: object
                    required:
                      - jobId
                      - kind
                      - status
                      - scanResult
                      - mergeResult
                      - error
                    properties:
                      jobId:
                        type: string
                      kind:
                        type: string
                        enum:
                          - scan
                          - merge
                      status:
                        type: string
                        enum:
                          - pending
                          - processing
                          - completed
                          - failed
                      scanResult:
                        type:
                          - object
                          - 'null'
                        description: Set only when a SCAN job is completed; null otherwise.
                        properties:
                          matchFields:
                            type: array
                            items:
                              type: string
                          totalGroups:
                            type: integer
                          totalDuplicateContacts:
                            type: integer
                          totalContactsScanned:
                            type: integer
                          truncated:
                            type: boolean
                            description: >-
                              True when more than 200 groups were found and only
                              the first 200 are stored.
                          skippedOversizedGroups:
                            type: integer
                            description: >-
                              Groups skipped for exceeding 50 contacts (almost
                              certainly a too-weak field selection).
                          pagination:
                            type: object
                            description: >-
                              Paging over the STORED groups (at most 200).
                              totalRecords counts pageable groups; totalGroups
                              above counts every group found.
                            properties:
                              pageNum:
                                type: integer
                              totalPages:
                                type: integer
                              totalRecords:
                                type: integer
                          groups:
                            type: array
                            items:
                              type: object
                              properties:
                                groupId:
                                  type: string
                                  description: >-
                                    Stable 16-hex id — what POST
                                    /business/contacts/dedupe-merge selects by.
                                matchedValues:
                                  type: object
                                  description: >-
                                    The normalized values the group matched on,
                                    keyed by match field.
                                  additionalProperties:
                                    type: string
                                groupSize:
                                  type: integer
                                contactIds:
                                  type: array
                                  items:
                                    type: string
                                lists:
                                  type: array
                                  description: >-
                                    Lists the members live in (first 10,
                                    alphabetical); listCount is the full total.
                                  items:
                                    type: object
                                    properties:
                                      id:
                                        type: string
                                      name:
                                        type: string
                                listCount:
                                  type: integer
                                mergePreview:
                                  type: object
                                  description: >-
                                    What the surviving contact will look like
                                    after the merge.
                                  properties:
                                    winnerContactId:
                                      type: string
                                    firstName:
                                      type:
                                        - string
                                        - 'null'
                                    lastName:
                                      type:
                                        - string
                                        - 'null'
                                    jobTitle:
                                      type:
                                        - string
                                        - 'null'
                                    linkedinUrl:
                                      type:
                                        - string
                                        - 'null'
                                    industry:
                                      type:
                                        - string
                                        - 'null'
                                    kind:
                                      type: string
                                      enum:
                                        - canonical
                                        - custom
                                    companyName:
                                      type:
                                        - string
                                        - 'null'
                                    companyDomain:
                                      type:
                                        - string
                                        - 'null'
                                    location:
                                      type:
                                        - string
                                        - 'null'
                                    primaryEmail:
                                      type:
                                        - string
                                        - 'null'
                                    emailCount:
                                      type: integer
                                    emails:
                                      type: array
                                      items:
                                        type: object
                                        properties:
                                          email:
                                            type: string
                                          status:
                                            type:
                                              - string
                                              - 'null'
                                          isPersonal:
                                            type: boolean
                                    primaryPhone:
                                      type:
                                        - string
                                        - 'null'
                                    phoneCount:
                                      type: integer
                                    phones:
                                      type: array
                                      items:
                                        type: object
                                        properties:
                                          phoneNumber:
                                            type: string
                                          status:
                                            type:
                                              - string
                                              - 'null'
                                contacts:
                                  type: array
                                  description: >-
                                    Preview of the first 25 members (contactIds
                                    carries every member).
                                  items:
                                    type: object
                                    properties:
                                      contactId:
                                        type: string
                                      firstName:
                                        type:
                                          - string
                                          - 'null'
                                      lastName:
                                        type:
                                          - string
                                          - 'null'
                                      jobTitle:
                                        type:
                                          - string
                                          - 'null'
                                      linkedinUrl:
                                        type:
                                          - string
                                          - 'null'
                                      kind:
                                        type: string
                                        enum:
                                          - canonical
                                          - custom
                                      companyName:
                                        type:
                                          - string
                                          - 'null'
                                      companyDomain:
                                        type:
                                          - string
                                          - 'null'
                                      createdAt:
                                        type:
                                          - string
                                          - 'null'
                                      location:
                                        type:
                                          - string
                                          - 'null'
                                      primaryEmail:
                                        type:
                                          - string
                                          - 'null'
                                      emailCount:
                                        type: integer
                                      emails:
                                        type: array
                                        items:
                                          type: object
                                      primaryPhone:
                                        type:
                                          - string
                                          - 'null'
                                      phoneCount:
                                        type: integer
                                      phones:
                                        type: array
                                        items:
                                          type: object
                      mergeResult:
                        type:
                          - object
                          - 'null'
                        description: >-
                          Set only when a MERGE job is completed; null
                          otherwise.
                        properties:
                          mergedGroups:
                            type: integer
                          archivedContacts:
                            type: integer
                          skippedGroups:
                            type: integer
                            description: >-
                              Groups that merged nothing: fewer than two live
                              members when the merge ran, or conflicting Fuse
                              identities.
                      error:
                        type:
                          - string
                          - 'null'
                        enum:
                          - DEDUPE_FAILED
                          - null
              example:
                dedupeJob:
                  jobId: 68a1f5209c41d20014b3eb11
                  kind: scan
                  status: completed
                  scanResult:
                    matchFields:
                      - email
                    totalGroups: 1
                    totalDuplicateContacts: 2
                    totalContactsScanned: 4056
                    truncated: false
                    skippedOversizedGroups: 0
                    pagination:
                      pageNum: 1
                      totalPages: 1
                      totalRecords: 1
                    groups:
                      - groupId: 3f6c2a9d1b8e4c7f
                        matchedValues:
                          email: ada@brightpay.com
                        groupSize: 2
                        contactIds:
                          - 68a1f2c89c41d20014b3e955
                          - 68a1f2c89c41d20014b3e956
                        lists:
                          - id: 68a1f20b9c41d20014b3e901
                            name: European fintech Series A
                        listCount: 1
                        mergePreview:
                          winnerContactId: 68a1f2c89c41d20014b3e955
                          firstName: Ada
                          lastName: Nwosu
                          jobTitle: Head of Payroll
                          linkedinUrl: https://www.linkedin.com/in/ada-nwosu
                          industry: Financial Services
                          kind: canonical
                          companyName: Brightpay
                          companyDomain: brightpay.com
                          location: Dublin, Leinster, Ireland
                          primaryEmail: ada@brightpay.com
                          emailCount: 2
                          emails:
                            - email: ada@brightpay.com
                              status: valid
                              isPersonal: false
                            - email: ada.nwosu@gmail.com
                              status: valid
                              isPersonal: true
                          primaryPhone: '+353871234567'
                          phoneCount: 1
                          phones:
                            - phoneNumber: '+353871234567'
                              status: valid
                        contacts:
                          - contactId: 68a1f2c89c41d20014b3e955
                            firstName: Ada
                            lastName: Nwosu
                            jobTitle: Head of Payroll
                            linkedinUrl: https://www.linkedin.com/in/ada-nwosu
                            kind: canonical
                            companyName: Brightpay
                            companyDomain: brightpay.com
                            createdAt: '2026-05-02T09:14:33.000Z'
                            location: Dublin, Leinster, Ireland
                            primaryEmail: ada@brightpay.com
                            emailCount: 1
                            emails:
                              - email: ada@brightpay.com
                                status: valid
                                isPersonal: false
                            primaryPhone: '+353871234567'
                            phoneCount: 1
                            phones:
                              - phoneNumber: '+353871234567'
                                status: valid
                          - contactId: 68a1f2c89c41d20014b3e956
                            firstName: Ada
                            lastName: Nwosu
                            jobTitle: null
                            linkedinUrl: null
                            kind: custom
                            companyName: Brightpay
                            companyDomain: null
                            createdAt: '2026-08-11T16:40:02.000Z'
                            location: null
                            primaryEmail: ada@brightpay.com
                            emailCount: 2
                            emails:
                              - email: ada@brightpay.com
                                status: valid
                                isPersonal: false
                              - email: ada.nwosu@gmail.com
                                status: valid
                                isPersonal: true
                            primaryPhone: null
                            phoneCount: 0
                            phones: []
                  mergeResult: null
                  error: null
        '400':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '402':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      security:
        - basicAuth: []
components:
  schemas:
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
            message:
              type: string
            param:
              type:
                - string
                - 'null'
            doc_url:
              type:
                - string
                - 'null'
            request_id:
              type:
                - string
                - 'null'
          required:
            - code
            - message
      required:
        - error
  securitySchemes:
    basicAuth:
      type: http
      scheme: basic
      description: >-
        Your API token (`af_…`) as the Basic-auth username, with an empty
        password.

````

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