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

# List candidates

> Pages through the workspace’s company candidates, by review priority unless `sort` says otherwise. Filter by job, status, scores or source. Pass `rankingMode` with `sort=contextual_priority` for a ranked list (`contextualRanking.available` says whether the workspace can have one); its rows also carry a `recommendation`. A ranked sort without `rankingMode`, or another sort with it, is refused with `invalid_sort`.



## OpenAPI

````yaml https://api.enrik.ai/v1/openapi.json get /v1/company-candidates
openapi: 3.1.2
info:
  title: Enrik API
  version: v1
  description: >-
    The public Enrik API, version 1. It is a server-to-server API: call it from
    your backend, never from a browser. It sends no CORS headers, and an
    `OPTIONS` request to an API path answers `405 method_not_allowed`.
    Authenticate with an API key sent as a Bearer token; each operation lists
    the scopes the key needs, and the `apiKey` security scheme says what each
    scope grants. Operations marked `x-stability-level: beta` may still change;
    `stable` ones change only in a new version. A query parameter or body field
    an operation does not declare is refused with `422 validation_error`, naming
    it. Every error answers the same envelope: branch on the HTTP status and
    `error.code`, whose known values `ErrorInfo` lists.
  contact:
    name: Enrik support
    email: support@enrik.ai
    url: https://docs.enrik.ai
servers:
  - url: https://api.enrik.ai
    description: Production
security: []
tags:
  - name: apiKeys
    description: >-
      API keys. Public, for any authenticated key: `GET /v1/me`, where it reads
      its own id, name, display prefix, expiry, workspace and scopes, and `POST
      /v1/me/rotate` and `POST /v1/me/revoke`, where it rotates its own secret
      or revokes itself. Minting, listing, rotating and revoking other keys is
      internal: an owner or admin does it in Settings → API keys.
  - name: companies
    description: >-
      Companies: the organisations in your workspace, with their contacts,
      timeline and where their facts came from.
  - name: companyCandidates
    description: >-
      Company candidates: companies a discovery job found, or a user added,
      waiting for review. Accept, reject (dismiss), archive and promote them,
      one at a time or in bulk.
  - name: companyDiscoveryJobs
    description: >-
      Company discovery jobs: searches for candidate companies from one source,
      with their candidates and a quality summary. Read-only here; running a job
      stays in the app.
  - name: companySignals
    description: >-
      Company signals: displayed signals about one company, with their evidence.
      Manual writes are internal session operations.
  - name: contacts
    description: 'Contacts: the people in your workspace, with their timeline.'
  - name: customFieldDefinitions
    description: >-
      Custom fields: the fields a workspace added to its contacts and companies,
      which their `customFields` hold by key.
  - name: discoveryBriefs
    description: >-
      Discovery briefs: how to find and judge companies for one ICP profile
      version, and their immutable versions. Read-only here.
  - name: exportFields
    description: >-
      The fields an export can carry, the workspace’s custom and recommendation
      fields included.
  - name: exportJobs
    description: >-
      CSV exports of companies, contacts and candidates: create a draft, preview
      it, start it, poll it and download the file. A key reads them with
      `exports:read` and runs them with `exports:run` and `crm:read`; delivery
      to a webhook destination stays in the app.
  - name: feedback
    description: >-
      Anonymous agent feedback about the public API. Any authenticated API key
      may send a note, which is stored with no sender; the report is an internal
      operator read.
  - name: health
    description: >-
      Whether the API is up: `GET /v1/health`, public and needing no API key, is
      the API catalog’s `status` link. The liveness and readiness probes for
      load balancers stay internal.
  - name: icpAssessments
    description: >-
      ICP assessments: how one company fares against an ICP profile version, as
      stored. Reading never evaluates.
  - name: icpProfiles
    description: >-
      ICP profiles: ideal customer profiles and the immutable versions that hold
      their criteria. Read-only here.
  - name: savedViews
    description: >-
      Saved views: named sets of filters, sort and columns over contacts or
      companies, which replay to the same records as the equivalent list query.
  - name: signalDefinitions
    description: >-
      Signal definitions: the signals the workspace looks for in companies, and
      the immutable versions that say what they are. Read-only here.
  - name: signalDetectors
    description: >-
      Signal detectors: the kinds of detector a signal definition can use, and
      why any cannot run.
  - name: webhookEventDeliveries
    description: 'The delivery log of webhook events: states and attempts, never a body.'
  - name: webhookEventTypes
    description: >-
      The webhook event types a subscription can name, and the permission and
      key scope each needs.
  - name: webhookSubscriptions
    description: >-
      Webhook subscriptions: which events Enrik sends, signed, to a receiver
      URL; edit, test, pause, resume and archive them, and rotate their signing
      secret. Owners and admins manage them, and grant `webhooks:write` to a
      key.
  - name: websiteOnboarding
    description: >-
      Workspace company setup: shared profile confirmation and durable command
      receipts. Public scoped setup operations and internal handoff/artifact
      projections.
  - name: workspaceMembers
    description: >-
      Workspace members: the people who use the workspace, as the user id and
      name a contact’s or company’s `ownerUserId` takes. Read-only.
externalDocs:
  description: Guides, authentication, errors, scopes and pagination.
  url: https://docs.enrik.ai
paths:
  /v1/company-candidates:
    get:
      tags:
        - companyCandidates
      summary: List candidates
      description: >-
        Pages through the workspace’s company candidates, by review priority
        unless `sort` says otherwise. Filter by job, status, scores or source.
        Pass `rankingMode` with `sort=contextual_priority` for a ranked list
        (`contextualRanking.available` says whether the workspace can have one);
        its rows also carry a `recommendation`. A ranked sort without
        `rankingMode`, or another sort with it, is refused with `invalid_sort`.
      operationId: companyCandidates.list
      parameters:
        - name: rankingMode
          in: query
          required: false
          description: >-
            Rank the candidates: `icp_only` against the ICP profile,
            `contextual` against a brief.
          schema:
            type: string
            enum:
              - icp_only
              - contextual
        - name: sort
          in: query
          required: false
          description: >-
            Sort by one score, highest first, or by `createdAt`, newest first. A
            ranked list sorts by `contextual_priority`, and only by it. Without
            it, candidates come by review priority.
          schema:
            type: string
            enum:
              - reviewPriorityScore
              - candidateIcpFitScore
              - candidateQualityScore
              - candidateEvidenceScore
              - createdAt
              - contextual_priority
        - name: briefId
          in: query
          required: false
          description: 'A contextual ranked list: the brief to rank against.'
          schema:
            type: string
            format: uuid
            pattern: >-
              ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$
        - name: briefVersionId
          in: query
          required: false
          description: 'A contextual ranked list: the exact brief version to rank against.'
          schema:
            type: string
            format: uuid
            pattern: >-
              ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$
        - name: snoozed
          in: query
          required: false
          description: >-
            A ranked list: leave snoozed candidates out (`exclude`, the
            default), in, or only.
          schema:
            type: string
            enum:
              - exclude
              - include
              - only
        - name: customerStatus
          in: query
          required: false
          description: 'A ranked list: only candidates with this customer status.'
          schema:
            type: string
            enum:
              - customer
              - not_customer
              - unavailable
        - name: salesWorkState
          in: query
          required: false
          description: 'A ranked list: only candidates in this state of sales work.'
          schema:
            type: string
            enum:
              - in_sales_work
              - not_in_sales_work
              - unavailable
        - $ref: '#/components/parameters/Cursor'
        - name: discoveryJobId
          in: query
          required: false
          description: Only the candidates of this discovery job.
          schema:
            type: string
            format: uuid
            pattern: >-
              ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$
        - name: status
          in: query
          required: false
          description: Only candidates in this status.
          schema:
            type: string
            enum:
              - new
              - needs_review
              - accepted
              - rejected
              - archived
              - promoted
              - linked_existing
              - failed
        - name: dedupeStatus
          in: query
          required: false
          description: Only candidates with this duplicate status.
          schema:
            type: string
            enum:
              - unchecked
              - no_match
              - possible_duplicate
              - existing_company_match
              - duplicate_candidate
        - name: scoringStatus
          in: query
          required: false
          description: Only candidates with this scoring status.
          schema:
            type: string
            enum:
              - unscored
              - scored
              - failed
              - stale
        - name: reviewPriorityTier
          in: query
          required: false
          description: Only candidates in this review-priority band.
          schema:
            type: string
            enum:
              - high_priority
              - medium_priority
              - low_priority
              - reject_likely
              - insufficient_data
        - name: recommendedAction
          in: query
          required: false
          description: Only candidates with this recommended next action.
          schema:
            type: string
            enum:
              - promote_candidate
              - review_manually
              - verify_domain
              - possible_duplicate_review
              - reject_candidate
              - insufficient_data
        - name: sourceType
          in: query
          required: false
          description: Only candidates from this kind of source.
          schema:
            type: string
            enum:
              - pasted_list
              - manual_candidate
              - user_provided_source_page
              - controlled_source
              - csv_upload
              - enrik_data
              - infobel_firmographics
        - name: sourceCategory
          in: query
          required: false
          description: Only candidates from this category of controlled source.
          schema:
            type: string
            enum:
              - trade_fair_exhibitor
              - event_sponsor
              - industry_directory
              - association_member_list
              - conference_partner
              - other_structured_b2b_list
        - name: minReviewPriorityScore
          in: query
          required: false
          description: >-
            Only candidates with at least this review priority, 0 to 100. Empty
            means no minimum.
          schema:
            type: string
        - name: minIcpFitScore
          in: query
          required: false
          description: >-
            Only candidates with at least this ICP fit, 0 to 100. Empty means no
            minimum.
          schema:
            type: string
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/IfNoneMatch'
      responses:
        '200':
          description: >-
            A page of candidates: by review priority, by the `sort` asked for,
            or ranked (`rankingMode`).
          headers:
            RateLimit:
              $ref: '#/components/headers/RateLimit'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimitPolicy'
            ETag:
              $ref: '#/components/headers/ETag'
            Cache-Control:
              $ref: '#/components/headers/CacheControl'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CompanyCandidateList'
              example:
                data:
                  - id: 0199a1b2-0000-7000-8000-00000000e001
                    discoveryJobId: 0199a1b2-0000-7000-8000-00000000d001
                    icpProfileId: 0199a1b2-0000-7000-8000-00000000f001
                    icpProfileVersionId: 0199a1b2-0000-7000-8000-00000000f011
                    discoveryBriefId: null
                    name: Alpine Robotics GmbH
                    normalizedName: alpine robotics
                    website: https://alpine-robotics.example
                    domain: alpine-robotics.example
                    normalizedDomain: alpine-robotics.example
                    country: AT
                    description: Industrial robot cells for small manufacturers.
                    sourceType: pasted_list
                    sourceLabel: Trade fair shortlist
                    sourceUrl: null
                    sourceRowIndex: 0
                    sourcePayload:
                      row: Alpine Robotics GmbH, alpine-robotics.example
                    status: needs_review
                    dedupeStatus: no_match
                    domainVerificationStatus: verified
                    confidence: high
                    matchedCompanyId: null
                    promotedCompanyId: null
                    createdBy: 0199a1b2-0000-7000-8000-00000000c001
                    updatedBy: 0199a1b2-0000-7000-8000-00000000c001
                    createdAt: '2026-09-29T08:00:07.000Z'
                    updatedAt: '2026-09-29T08:00:08.000Z'
                    candidateQualityScore: 90
                    candidateIcpFitScore: 75
                    candidateEvidenceScore: 60
                    sourceConfidenceScore: 70
                    reviewPriorityScore: 78
                    reviewPriorityTier: medium_priority
                    recommendedAction: review_manually
                    scoringStatus: scored
                    scoredAt: '2026-09-29T08:00:08.000Z'
                    scoringVersion: deterministic-v1
                    scoringMetadata:
                      scoringMode: deterministic
                      scoringVersion: deterministic-v1
                      icpProfileId: 0199a1b2-0000-7000-8000-00000000f001
                      icpProfileVersionId: 0199a1b2-0000-7000-8000-00000000f011
                      discoveryBriefId: null
                      inputs:
                        - name
                        - website
                        - country
                        - description
                      scoreBreakdown:
                        candidateQuality:
                          score: 90
                          reasons:
                            - Name, website and description are present.
                        icpFit:
                          score: 75
                          reasons:
                            - The country matches.
                            - The industry matches.
                        evidence:
                          score: 60
                          reasons:
                            - The website was verified.
                        sourceConfidence:
                          score: 70
                          reasons:
                            - A pasted list from a known trade fair.
                      penalties: []
                    canonicalCompanyId: null
                    entityCompanyId: null
                    sourceProfileStatus: null
                    workspaceMatchStatus: null
                    workspaceCompanyId: null
                    enrikSnapshotVersion: null
                    profileFetchedAt: null
                    retrievalQuery: null
                    retrievalReasons: null
                pageInfo:
                  hasNextPage: false
                  endCursor: null
                  limit: 50
                contextualRanking:
                  available: true
        '304':
          $ref: '#/components/responses/NotModified'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '422':
          $ref: '#/components/responses/UnprocessableContent'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalServerError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
        default:
          $ref: '#/components/responses/Error'
      security:
        - apiKey:
            - discovery:read
components:
  parameters:
    Cursor:
      name: cursor
      in: query
      required: false
      description: >-
        Where to resume a list: the previous page’s `pageInfo.endCursor`.
        Opaque.
      schema:
        type: string
        minLength: 1
    Limit:
      name: limit
      in: query
      required: false
      description: 'How many items to return: 1 to 200, 50 when absent.'
      schema:
        default: 50
        type: integer
        minimum: 1
        maximum: 200
    IfNoneMatch:
      name: If-None-Match
      in: header
      required: false
      description: >-
        The `ETag` of an answer you kept. While the answer is still the same,
        the API answers `304 Not Modified` with no body. Several tags, separated
        by commas, a weak tag (`W/"…"`) and `*` are accepted.
      schema:
        type: string
  headers:
    RateLimit:
      description: >-
        What the API key has left under each rate-limit policy that counted this
        request: a Structured Field list with one
        `"<policy>";r=<remaining>;t=<seconds>` item per policy. Read it as a
        list and honour every item, not only the smallest: continued traffic
        must satisfy each policy. `t` is the effective window in seconds (IETF
        RateLimit header fields, draft 11): quota is not guaranteed to be fully
        restored when it ends. When the answer also carries `Retry-After`, that
        takes priority. One policy counts this operation: `api-key`, every
        request the key makes.
      schema:
        type: string
      example: '"api-key";r=599;t=60'
    RateLimitPolicy:
      description: >-
        The rate-limit policies that counted this request: a Structured Field
        list with one `"<policy>";q=<requests>;w=<window in seconds>` item per
        policy. The limits belong to the key, not to the address it calls from.
        One policy counts this operation: `api-key`, every request the key
        makes.
      schema:
        type: string
      example: '"api-key";q=600;w=60'
    ETag:
      description: >-
        The answer’s entity tag: the base64url SHA-256 of the JSON body as sent,
        quoted. It changes whenever the body does. Send it as `If-None-Match` to
        be answered `304 Not Modified` while the answer is the same. It is taken
        over your answer only, after your scopes and fields are applied.
      schema:
        type: string
      example: '"heLt3E-oE86d1oB1ENqD3g27HyZvOWn-1MuHraYky2Y"'
    CacheControl:
      description: >-
        `private, no-cache`: a cache may keep the answer for this caller only,
        and must check it with `If-None-Match` before using it again.
      schema:
        type: string
      example: private, no-cache
    RetryAfter:
      description: >-
        Seconds to wait before retrying. It takes priority over the `t` of every
        `RateLimit` item.
      schema:
        type: integer
        minimum: 1
      example: 60
  schemas:
    CompanyCandidateList:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/CompanyCandidateListItem'
          description: The items on this page, in order.
        pageInfo:
          $ref: '#/components/schemas/PageInfo'
          description: Where this page ends, and whether another follows.
        contextualRanking:
          $ref: '#/components/schemas/CandidateContextualRanking'
          description: Whether a ranked list can be asked for.
      required:
        - data
        - pageInfo
        - contextualRanking
      additionalProperties: true
      description: >-
        A page of candidates: by review priority, by the `sort` asked for, or
        ranked (`rankingMode`).
    CompanyCandidateListItem:
      type: object
      properties:
        id:
          type: string
          description: The candidate’s id.
        discoveryJobId:
          description: >-
            The discovery job that found the candidate; `null` for one added by
            hand.
          type:
            - string
            - 'null'
        icpProfileId:
          description: >-
            The ICP profile the candidate was found for; `null` when there was
            none.
          type:
            - string
            - 'null'
        icpProfileVersionId:
          description: The exact version of that ICP profile; `null` when there was none.
          type:
            - string
            - 'null'
        discoveryBriefId:
          description: >-
            The discovery brief the candidate was found for; `null` when there
            was none.
          type:
            - string
            - 'null'
        name:
          type: string
          description: The company’s name.
        normalizedName:
          type: string
          description: The name normalised for matching.
        website:
          description: The company’s website; `null` when unknown.
          type:
            - string
            - 'null'
        domain:
          description: The website’s domain; `null` when unknown.
          type:
            - string
            - 'null'
        normalizedDomain:
          description: The domain normalised for matching; `null` when unknown.
          type:
            - string
            - 'null'
        country:
          description: The company’s country; `null` when unknown.
          type:
            - string
            - 'null'
        description:
          description: What the company does; `null` when unknown.
          type:
            - string
            - 'null'
        sourceType:
          type: string
          enum:
            - pasted_list
            - manual_candidate
            - user_provided_source_page
            - controlled_source
            - csv_upload
            - enrik_data
            - infobel_firmographics
          description: The kind of source the candidate came from.
        sourceLabel:
          description: A label for the source; `null` when there is none.
          type:
            - string
            - 'null'
        sourceUrl:
          description: The page the candidate was found on; `null` when there is none.
          type:
            - string
            - 'null'
        sourceRowIndex:
          anyOf:
            - type: integer
              minimum: -9007199254740991
              maximum: 9007199254740991
            - type: 'null'
          description: The candidate’s row in a pasted or uploaded list; `null` otherwise.
        sourcePayload:
          type: object
          propertyNames:
            type: string
          additionalProperties: {}
          description: >-
            What the source said about the candidate. Its shape depends on
            `sourceType`.
        status:
          type: string
          enum:
            - new
            - needs_review
            - accepted
            - rejected
            - archived
            - promoted
            - linked_existing
            - failed
          description: >-
            Where the candidate is in review: new, accepted, rejected, promoted
            and so on.
        dedupeStatus:
          type: string
          enum:
            - unchecked
            - no_match
            - possible_duplicate
            - existing_company_match
            - duplicate_candidate
          description: >-
            Whether the candidate matches a company or candidate the workspace
            already has.
        domainVerificationStatus:
          type: string
          enum:
            - unchecked
            - verified
            - inferred
            - failed
            - not_available
          description: Whether the website was checked to belong to the company.
        confidence:
          type: string
          enum:
            - low
            - medium
            - high
          description: How confident the source is about the candidate.
        matchedCompanyId:
          description: The workspace company the candidate matches; `null` when none.
          type:
            - string
            - 'null'
        promotedCompanyId:
          description: The company the candidate was promoted to; `null` until it is.
          type:
            - string
            - 'null'
        createdBy:
          description: The user who added the candidate; `null` when no user did.
          type:
            - string
            - 'null'
        updatedBy:
          description: The user who last changed the candidate; `null` when no user did.
          type:
            - string
            - 'null'
        createdAt:
          type: string
          format: date-time
          pattern: >-
            ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
          description: When the candidate was added.
        updatedAt:
          type: string
          format: date-time
          pattern: >-
            ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
          description: When the candidate last changed.
        candidateQualityScore:
          anyOf:
            - type: integer
              minimum: -9007199254740991
              maximum: 9007199254740991
            - type: 'null'
          description: >-
            How complete and usable the record is, 0 to 100; `null` until
            scored.
        candidateIcpFitScore:
          anyOf:
            - type: integer
              minimum: -9007199254740991
              maximum: 9007199254740991
            - type: 'null'
          description: >-
            How well the candidate fits the ICP profile, 0 to 100; `null` until
            scored.
        candidateEvidenceScore:
          description: >-
            How well the fit is supported by evidence, 0 to 100; `null` until
            scored.
          type:
            - number
            - 'null'
        sourceConfidenceScore:
          description: How far the source can be trusted, 0 to 100; `null` until scored.
          type:
            - number
            - 'null'
        reviewPriorityScore:
          anyOf:
            - type: integer
              minimum: -9007199254740991
              maximum: 9007199254740991
            - type: 'null'
          description: >-
            How urgently the candidate should be reviewed, 0 to 100; `null`
            until scored.
        reviewPriorityTier:
          anyOf:
            - type: string
              enum:
                - high_priority
                - medium_priority
                - low_priority
                - reject_likely
                - insufficient_data
            - type: 'null'
          description: The review-priority band; `null` until scored.
        recommendedAction:
          anyOf:
            - type: string
              enum:
                - promote_candidate
                - review_manually
                - verify_domain
                - possible_duplicate_review
                - reject_candidate
                - insufficient_data
            - type: 'null'
          description: What to do with the candidate next; `null` until scored.
        scoringStatus:
          type: string
          enum:
            - unscored
            - scored
            - failed
            - stale
          description: >-
            Whether the candidate is unscored, scored, failed to score, or
            stale.
        scoredAt:
          anyOf:
            - type: string
              format: date-time
              pattern: >-
                ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
            - type: 'null'
          description: When the candidate was scored; `null` until.
        scoringVersion:
          description: The scoring algorithm’s version; `null` until scored.
          type:
            - string
            - 'null'
        scoringMetadata:
          anyOf:
            - $ref: '#/components/schemas/CandidateScoringMetadata'
            - type: 'null'
          description: How the scores were reached; `null` until scored.
        canonicalCompanyId:
          description: >-
            The company in Enrik’s company data the candidate is; `null` for
            other sources.
          type:
            - string
            - 'null'
        entityCompanyId:
          description: The registered entity behind the candidate; `null` when unknown.
          type:
            - string
            - 'null'
        sourceProfileStatus:
          anyOf:
            - type: string
              enum:
                - enriched
                - registry_only
                - profile_fetch_failed
            - type: 'null'
          description: >-
            How complete the company profile from Enrik’s data is; `null` for
            other sources.
        workspaceMatchStatus:
          anyOf:
            - type: string
              enum:
                - already_linked
            - type: 'null'
          description: >-
            `already_linked` when the workspace already has the company; `null`
            otherwise.
        workspaceCompanyId:
          description: The workspace company already linked to it; `null` when none.
          type:
            - string
            - 'null'
        enrikSnapshotVersion:
          description: >-
            The version of Enrik’s data the candidate came from; `null` for
            other sources.
          type:
            - string
            - 'null'
        profileFetchedAt:
          anyOf:
            - type: string
              format: date-time
              pattern: >-
                ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
            - type: 'null'
          description: When the company profile was fetched; `null` when it was not.
        retrievalQuery:
          description: The search that found the candidate; `null` for other sources.
          type:
            - string
            - 'null'
        retrievalReasons:
          anyOf:
            - type: array
              items:
                type: string
            - type: 'null'
          description: Why the search returned the candidate; `null` for other sources.
        recommendation:
          $ref: '#/components/schemas/CandidateRecommendation'
          description: >-
            Where the candidate stands; present only in a ranked list
            (`rankingMode`).
        customerStatus:
          description: >-
            Whether the company is a customer; present only in a ranked list,
            `null` for a candidate.
          anyOf:
            - type: string
              enum:
                - customer
                - not_customer
            - type: 'null'
        salesWorkState:
          description: >-
            Whether sales work is under way; present only in a ranked list,
            `null` for a candidate.
          anyOf:
            - type: string
              enum:
                - in_sales_work
                - not_in_sales_work
            - type: 'null'
        snoozeUntil:
          description: Until when the candidate is snoozed; present only in a ranked list.
          anyOf:
            - type: string
              format: date-time
              pattern: >-
                ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
            - type: 'null'
      required:
        - id
        - discoveryJobId
        - icpProfileId
        - icpProfileVersionId
        - discoveryBriefId
        - name
        - normalizedName
        - website
        - domain
        - normalizedDomain
        - country
        - description
        - sourceType
        - sourceLabel
        - sourceUrl
        - sourceRowIndex
        - sourcePayload
        - status
        - dedupeStatus
        - domainVerificationStatus
        - confidence
        - matchedCompanyId
        - promotedCompanyId
        - createdBy
        - updatedBy
        - createdAt
        - updatedAt
        - candidateQualityScore
        - candidateIcpFitScore
        - candidateEvidenceScore
        - sourceConfidenceScore
        - reviewPriorityScore
        - reviewPriorityTier
        - recommendedAction
        - scoringStatus
        - scoredAt
        - scoringVersion
        - scoringMetadata
        - canonicalCompanyId
        - entityCompanyId
        - sourceProfileStatus
        - workspaceMatchStatus
        - workspaceCompanyId
        - enrikSnapshotVersion
        - profileFetchedAt
        - retrievalQuery
        - retrievalReasons
      additionalProperties: true
      description: >-
        A candidate in the candidate list. In a ranked list it also says where
        it stands and why.
    PageInfo:
      type: object
      properties:
        hasNextPage:
          type: boolean
          description: Whether another page follows this one.
        endCursor:
          description: >-
            Pass it as `cursor` to fetch the next page; `null` when there is
            none to resume from.
          type:
            - string
            - 'null'
        limit:
          type: integer
          minimum: -9007199254740991
          maximum: 9007199254740991
          description: The page size that applied to this page.
      required:
        - hasNextPage
        - endCursor
        - limit
      additionalProperties: true
      description: Where a page of a list ends, and whether another follows.
    CandidateContextualRanking:
      type: object
      properties:
        available:
          type: boolean
          description: >-
            Whether a ranked list (`rankingMode`) can be asked for in this
            workspace.
      required:
        - available
      additionalProperties: true
      description: >-
        Whether the candidate list can be ranked against an ICP profile or a
        brief.
    ErrorEnvelope:
      type: object
      properties:
        error:
          $ref: '#/components/schemas/ErrorInfo'
          description: >-
            What went wrong: the code to branch on, a message and the request
            id.
      required:
        - error
      additionalProperties: true
      description: The body of every error response.
    CandidateScoringMetadata:
      type: object
      properties:
        scoringMode:
          type: string
          const: deterministic
          description: How the candidate was scored.
        scoringVersion:
          type: string
          description: The version of the scoring algorithm.
        icpProfileId:
          description: The ICP profile scored against; `null` when there was none.
          type:
            - string
            - 'null'
        icpProfileVersionId:
          description: The ICP profile version scored against; `null` when there was none.
          type:
            - string
            - 'null'
        discoveryBriefId:
          description: The discovery brief scored against; `null` when there was none.
          type:
            - string
            - 'null'
        inputs:
          type: array
          items:
            type: string
          description: The inputs the score was computed from.
        scoreBreakdown:
          $ref: '#/components/schemas/CandidateScoreBreakdown'
          description: The score of each dimension, with reasons.
        penalties:
          type: array
          items:
            $ref: '#/components/schemas/CandidateScorePenalty'
          description: The penalties that were applied.
      required:
        - scoringMode
        - scoringVersion
        - icpProfileId
        - icpProfileVersionId
        - discoveryBriefId
        - inputs
        - scoreBreakdown
        - penalties
      additionalProperties: true
      description: How a candidate’s scores were reached.
    CandidateRecommendation:
      type: object
      properties:
        state:
          type: string
          enum:
            - current
            - stale
            - withheld
            - missing
          description: >-
            Whether the recommendation is `current`, `stale`, `missing` (never
            evaluated) or `withheld`.
        staleReasons:
          type: array
          items:
            type: string
            enum:
              - result_expired
              - input_changed
              - rights_withheld
              - dismissed
              - snoozed
              - account_context_changed
              - policy_incompatible
              - brief_unavailable
          description: Why a stale recommendation is stale; empty otherwise.
        snapshotId:
          description: >-
            The evaluation the recommendation comes from; `null` when there is
            none.
          type:
            - string
            - 'null'
        tier:
          anyOf:
            - type: string
              enum:
                - qualified
                - review_needed
                - currently_unsatisfied
                - suppressed_excluded
            - type: 'null'
          description: The eligibility tier; `null` when there is none.
        timingCategory:
          anyOf:
            - type: string
              enum:
                - supported_event
                - condition_observed
                - outside_window
                - unknown
                - not_configured
            - type: 'null'
          description: What the timing evidence says; `null` when there is none.
        effectiveTimingGroup:
          anyOf:
            - type: string
              enum:
                - supported_now
                - condition_observed
                - unknown
                - outside_window
            - type: 'null'
          description: The timing group the list sorts by; `null` when there is none.
        fitScore:
          description: The fit score, 0 to 100; `null` when there is none.
          type:
            - number
            - 'null'
        fitCoverage:
          description: >-
            How much of the profile could be assessed, 0 to 1; `null` when there
            is none.
          type:
            - number
            - 'null'
        validUntil:
          anyOf:
            - type: string
              format: date-time
              pattern: >-
                ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
            - type: 'null'
          description: When the recommendation expires; `null` when there is none.
        reasons:
          type: array
          items:
            type: string
            enum:
              - icp_fit_satisfied
              - signal_required_passed
              - signal_boost_passed
              - signal_boost_failed
              - signal_boost_unknown
              - signals_not_configured
              - icp_required_uncertain
              - icp_insufficient_coverage
              - icp_required_partial
              - signal_required_unknown
              - signal_exclude_unknown
              - icp_required_failed
              - signal_required_failed
              - icp_hard_exclusion_verified
              - signal_exclude_passed
              - commercial_dismissal
              - icp_review_suppression
              - snoozed
          description: Every reason behind the tier.
      required:
        - state
        - staleReasons
        - snapshotId
        - tier
        - timingCategory
        - effectiveTimingGroup
        - fitScore
        - fitCoverage
        - validUntil
        - reasons
      additionalProperties: true
      description: Where a candidate stands in a ranked list, and why.
    ErrorInfo:
      type: object
      properties:
        code:
          type: string
          x-extensible-enum:
            - malformed_json
            - invalid_sort
            - unauthenticated
            - insufficient_scope
            - permission_denied
            - beta_access_required
            - not_a_member
            - not_found
            - method_not_allowed
            - conflict
            - stale_version
            - idempotency_key_reused
            - request_in_flight
            - company_twin_research_already_running
            - company_twin_own_domain_conflict
            - concurrent_run_limit
            - gone
            - payload_too_large
            - unsupported_media_type
            - validation_error
            - rate_limited
            - internal_error
            - response_contract_violation
            - service_unavailable
          description: >-
            A stable, machine-readable code such as `not_found`. Branch on this,
            not on `message`. The known values are every code a public operation
            answers; more may be added, so handle an unknown one by its HTTP
            status.
        message:
          type: string
          description: A human-readable explanation. It may change; do not parse it.
        requestId:
          type: string
          description: >-
            The id of the request that failed. Quote it when you contact
            support.
        details:
          description: >-
            Structured detail for some codes. For `validation_error` it is
            usually an array with one entry per problem: `path` (the field,
            dotted), `message` and, where the case has a name, `code` (such as
            `related_record_not_found`). Other codes that cover several cases
            carry an object whose `code` names the case (such as
            `invalid_cursor`).
      required:
        - code
        - message
        - requestId
      additionalProperties: true
      description: What went wrong.
    CandidateScoreBreakdown:
      type: object
      properties:
        candidateQuality:
          $ref: '#/components/schemas/CandidateScoreBreakdownEntry'
          description: How complete and usable the record is.
        icpFit:
          $ref: '#/components/schemas/CandidateScoreBreakdownEntry'
          description: How well the candidate fits the ICP profile.
        evidence:
          $ref: '#/components/schemas/CandidateScoreBreakdownEntry'
          description: How well the fit is supported by evidence.
        sourceConfidence:
          $ref: '#/components/schemas/CandidateScoreBreakdownEntry'
          description: How far the source can be trusted.
      required:
        - candidateQuality
        - icpFit
        - evidence
        - sourceConfidence
      additionalProperties: true
      description: The four scored dimensions of a candidate.
    CandidateScorePenalty:
      type: object
      properties:
        type:
          type: string
          description: What the penalty is for.
        points:
          type: integer
          minimum: -9007199254740991
          maximum: 9007199254740991
          description: How many points it took off the review priority.
      required:
        - type
        - points
      additionalProperties: true
      description: A penalty applied while scoring a candidate.
    CandidateScoreBreakdownEntry:
      type: object
      properties:
        score:
          description: The score, 0 to 100; `null` when it could not be given.
          type:
            - number
            - 'null'
        reasons:
          type: array
          items:
            type: string
          description: Why the score is what it is, one reason per entry.
      required:
        - score
        - reasons
      additionalProperties: true
      description: One scored dimension of a candidate.
  responses:
    NotModified:
      description: >-
        Not modified: the answer is still the one whose `ETag` the request sent
        in `If-None-Match`. There is no body; use the copy you kept.
      headers:
        ETag:
          $ref: '#/components/headers/ETag'
        Cache-Control:
          $ref: '#/components/headers/CacheControl'
    BadRequest:
      description: >-
        The request could not be read. Branch on `error.code`; quote
        `error.requestId` to support.


        The codes a public operation answers with it:


        - `malformed_json`: The body is not valid JSON, or is empty while
        `Content-Type` is `application/json`. Send valid JSON; omit
        `Content-Type` when there is no body.

        - `invalid_sort`: A sort names a field or direction the list does not
        support. Sort only by the fields the operation lists.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: malformed_json
              message: Bad Request
              requestId: 5b1d3c1e-8d6f-4f2a-9a57-3a9b1f2c7d10
    Unauthorized:
      description: >-
        The request is not authenticated. Branch on `error.code`; quote
        `error.requestId` to support.


        The codes a public operation answers with it:


        - `unauthenticated`: The key is missing, invalid, expired or revoked.
        Send a valid, unexpired key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: unauthenticated
              message: Unauthorized
              requestId: 5b1d3c1e-8d6f-4f2a-9a57-3a9b1f2c7d10
    Forbidden:
      description: >-
        The caller may not do this. Branch on `error.code`; quote
        `error.requestId` to support.


        The codes a public operation answers with it:


        - `insufficient_scope`: The key lacks a scope the operation, or a
        parameter such as `include` or `rankingMode`, needs.
        `details.missingScopes` names it; `WWW-Authenticate` lists every scope
        the request needs. Create a key with the missing scope.

        - `permission_denied`: The key’s scopes admit the operation, but its
        permissions do not cover this request: replaying a create needs
        `crm:read`, and a key keeps the permissions its scopes had when it was
        created. The message names the scope. Create a new key with the scope
        the message names.

        - `beta_access_required`: The workspace is not admitted to the beta,
        which every write except `feedback.submit` needs. Contact support.

        - `not_a_member`: `websiteOnboarding.getAccess`: the key’s workspace has
        been deleted. Use a key of a live workspace.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: insufficient_scope
              message: Forbidden
              requestId: 5b1d3c1e-8d6f-4f2a-9a57-3a9b1f2c7d10
    NotFound:
      description: >-
        Nothing was found. Branch on `error.code`; quote `error.requestId` to
        support.


        The codes a public operation answers with it:


        - `not_found`: No such record in your workspace. A path that is not part
        of the public API also answers `404`. Check the id and the path.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: not_found
              message: Not Found
              requestId: 5b1d3c1e-8d6f-4f2a-9a57-3a9b1f2c7d10
    Conflict:
      description: >-
        The request conflicts with the current state. Branch on `error.code`;
        quote `error.requestId` to support.


        The codes a public operation answers with it:


        - `conflict`: The request clashes with the current state, such as a
        duplicate domain or e-mail, a changed setup or a ranked list that
        changed. `details.code` names the case where there is one. Read fresh
        state, then decide.

        - `stale_version`: The record changed since the `expectedUpdatedAt` you
        sent. `details.currentUpdatedAt` is its current version. Read the record
        again and reapply your change.

        - `idempotency_key_reused`: The `Idempotency-Key` was used for a
        different command or body. Use a new key for a new command.

        - `request_in_flight`: The first request with this `Idempotency-Key` is
        still running. Retry shortly with the same key.

        - `company_twin_research_already_running`:
        `websiteOnboarding.confirmProfile`: research for this setup or website
        is already running. Read fresh setup state.

        - `company_twin_own_domain_conflict`:
        `websiteOnboarding.confirmProfile`: the website does not match the
        workspace’s company profile. Read fresh setup state, then confirm the
        profile with its own website.

        - `concurrent_run_limit`: `companyDiscoveryJobs.start` by an API key:
        the workspace already has as many discovery jobs queued or running as a
        key may start beside. `details.code` names the cap. Wait for a job to
        finish, or cancel one, then start again.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: conflict
              message: Conflict
              requestId: 5b1d3c1e-8d6f-4f2a-9a57-3a9b1f2c7d10
    UnprocessableContent:
      description: >-
        The request cannot be used as sent. Branch on `error.code`; quote
        `error.requestId` to support.


        The codes a public operation answers with it:


        - `validation_error`: The request does not match the operation’s schema,
        a field names something that does not exist, or a value cannot be used,
        such as an id that is not a UUID, a date outside the years 0001–9999 in
        a filter, or an edited cursor. See `details`. Fix the request.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: validation_error
              message: Unprocessable Entity
              requestId: 5b1d3c1e-8d6f-4f2a-9a57-3a9b1f2c7d10
    RateLimited:
      description: >-
        Too many requests (`error.code` is `rate_limited`): the API key spent a
        rate-limit policy, or the network it calls from presented too many
        invalid keys. Wait `Retry-After` seconds before retrying; it takes
        priority over `RateLimit`.
      headers:
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
        RateLimit:
          $ref: '#/components/headers/RateLimit'
        RateLimit-Policy:
          $ref: '#/components/headers/RateLimitPolicy'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: rate_limited
              message: Too many requests
              requestId: 5b1d3c1e-8d6f-4f2a-9a57-3a9b1f2c7d10
    InternalServerError:
      description: >-
        The request failed on the server. Branch on `error.code`; quote
        `error.requestId` to support.


        The codes a public operation answers with it:


        - `internal_error`: Something failed on our side. Retry later; reuse a
        command’s idempotency key.

        - `response_contract_violation`: Our answer broke its own schema, so it
        was withheld. `details.committed` says whether a change was saved. If
        `committed` is true, read the state instead of resending. Quote the
        request id.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: internal_error
              message: Internal Server Error
              requestId: 5b1d3c1e-8d6f-4f2a-9a57-3a9b1f2c7d10
    ServiceUnavailable:
      description: >-
        The service is briefly unavailable. Branch on `error.code`; quote
        `error.requestId` to support.


        The codes a public operation answers with it:


        - `service_unavailable`: A create ran out of time, or the service is
        briefly unavailable. Retry later with the same idempotency key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: service_unavailable
              message: Service Unavailable
              requestId: 5b1d3c1e-8d6f-4f2a-9a57-3a9b1f2c7d10
    Error:
      description: >-
        The request failed. Branch on `error.code`; quote `error.requestId` to
        support.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: not_found
              message: Not found
              requestId: 5b1d3c1e-8d6f-4f2a-9a57-3a9b1f2c7d10
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      description: >-
        An Enrik API key, sent as `Authorization: Bearer <key>`. A key reaches
        public operations only, and only those whose scopes it holds. A few
        parameters need a scope beyond their operation’s, which the parameter
        names. The scopes:


        - `setup:read`: Read the workspace setup and its company profile.

        - `setup:run`: Change the setup: confirm the company profile, authorize
        sponsored drafting and background company research, choose what to set
        up and complete setup.

        - `workspace:read`: Read the workspace’s own profile: its health summary
        and setup state.

        - `crm:read`: Read companies with their signals, contacts and the saved
        views over them.

        - `crm:write`: Create, update and restore companies and contacts, and
        create, update and delete saved views.

        - `crm:delete`: Delete companies and contacts.

        - `twin:read`: Read the Company Twin: structured company knowledge and
        its signals.

        - `discovery:read`: Read ICP profiles, ICP assessments, discovery
        briefs, discovery jobs, candidates and the signal library.

        - `discovery:write`: Create and change ICP profiles, discovery briefs
        and signal-definition drafts, and review discovery candidates.

        - `discovery:run`: Create, start and cancel discovery jobs, and edit a
        draft one. Uses provider budget.

        - `enrichment:read`: Read the enrichment configuration and its results,
        including a record’s enrichment, formula and custom-API cells.

        - `enrichment:run`: Launch and cancel enrichment. Spends enrichment
        credits.

        - `automation:read`: Read workflows and agents with their run history,
        including a record’s agent cells.

        - `automation:run`: Run existing workflows and agents.

        - `exports:read`: Read export jobs and the fields an export can carry.

        - `exports:run`: Create, preview, start, cancel and archive CSV exports
        of companies, contacts and candidates, and download the file. Also needs
        `crm:read`. Delivering an export to a webhook destination stays in the
        app.

        - `integrations:read`: Read connections, field mappings, CRM sync jobs
        and webhook destinations.

        - `webhooks:read`: Read webhook subscriptions, the event types they can
        name and their delivery log.

        - `webhooks:write`: Subscribe a receiver URL to webhook events; edit,
        test, pause, resume and archive a subscription and rotate its signing
        secret; redeliver an event. Only workspace owners and admins can grant
        it.

        - `reporting:read`: Read analytics and dashboards.

        - `assistant:read`: Read the Assistant: its threads, messages and
        pending approvals.

        - `assistant:run`: Converse with the Assistant. Uses the workspace’s AI
        quota.

        - `assistant:write`: Approve or reject the changes the Assistant
        proposes.

````

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