> ## 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.

# Create or update up to 100 companies by domain

> Creates or updates up to 100 companies, each found by its `domain` as `companies.upsert` finds it: a company created needs `name` (else the item fails with `validation_error` at `name`), and a domain more than one live company has fails the item with `conflict`, `details.code` `ambiguous_domain`. The body is checked as a whole first: a malformed item refuses the request with 422 `validation_error` at its path, such as `items.3.name`, and nothing is written. Then the items run one after another, each in its own transaction, so one that fails leaves the others written. The answer is 200 with one result per item, in order, and the counts: a written item has `outcome` `created` or `updated` and the record; a failed one has `outcome` `failed` and an `error` in the error envelope’s shape, with the code and details the single upsert would have answered. Every item is keyed by its natural key, so sending the same body again is harmless: no `Idempotency-Key` is taken, and a failed request or failed items can simply be sent again. A request counts against the `api-key-bulk` rate-limit policy as well as `api-key`.



## OpenAPI

````yaml https://api.enrik.ai/v1/openapi.json post /v1/companies/bulk-upsert
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/companies/bulk-upsert:
    post:
      tags:
        - companies
      summary: Create or update up to 100 companies by domain
      description: >-
        Creates or updates up to 100 companies, each found by its `domain` as
        `companies.upsert` finds it: a company created needs `name` (else the
        item fails with `validation_error` at `name`), and a domain more than
        one live company has fails the item with `conflict`, `details.code`
        `ambiguous_domain`. The body is checked as a whole first: a malformed
        item refuses the request with 422 `validation_error` at its path, such
        as `items.3.name`, and nothing is written. Then the items run one after
        another, each in its own transaction, so one that fails leaves the
        others written. The answer is 200 with one result per item, in order,
        and the counts: a written item has `outcome` `created` or `updated` and
        the record; a failed one has `outcome` `failed` and an `error` in the
        error envelope’s shape, with the code and details the single upsert
        would have answered. Every item is keyed by its natural key, so sending
        the same body again is harmless: no `Idempotency-Key` is taken, and a
        failed request or failed items can simply be sent again. A request
        counts against the `api-key-bulk` rate-limit policy as well as
        `api-key`.
      operationId: companies.bulkUpsert
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CompanyBulkUpsertRequest'
            example:
              items:
                - domain: https://www.example.com
                  name: Analytical Engines
                  industry: Software
                - domain: shared.example
                  industry: Energy
      responses:
        '200':
          description: What a bulk write did, item by item.
          headers:
            RateLimit:
              $ref: '#/components/headers/BulkRateLimit'
            RateLimit-Policy:
              $ref: '#/components/headers/BulkRateLimitPolicy'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CompanyBulkWriteResult'
              example:
                results:
                  - index: 0
                    outcome: created
                    company:
                      id: 0199a1b2-0000-7000-8000-00000000d101
                      workspaceId: 0199a1b2-0000-7000-8000-00000000b001
                      name: Analytical Engines
                      domain: example.com
                      website: https://example.com
                      industry: Software
                      employeeCount: 120
                      annualRevenue: 12500000
                      address:
                        city: Vienna
                        country: AT
                      linkedinUrl: null
                      country: Austria
                      summary: Builds engines that compute.
                      city: Vienna
                      legalForm: GmbH
                      registerNumber: FN 123456a
                      buildingEnergyTags: null
                      ownerUserId: 0199a1b2-0000-7000-8000-00000000c001
                      customFields:
                        segment: enterprise
                      canonicalCompanyId: null
                      enrikUpdateAvailable: false
                      enrikSnapshotVersion: null
                      createdBy: 0199a1b2-0000-7000-8000-00000000c001
                      updatedBy: 0199a1b2-0000-7000-8000-00000000c001
                      createdAt: '2026-09-29T08:00:00.000Z'
                      updatedAt: '2026-09-29T08:00:00.000Z'
                      deletedAt: null
                      signalSummary: null
                  - index: 1
                    outcome: failed
                    error:
                      code: conflict
                      message: More than one live company has this domain
                      requestId: 5b1d3c1e-8d6f-4f2a-9a57-3a9b1f2c7d10
                      details:
                        code: ambiguous_domain
                        companyIds:
                          - 0199a1b2-0000-7000-8000-00000000d102
                          - 0199a1b2-0000-7000-8000-00000000d103
                created: 1
                updated: 0
                failed: 1
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '409':
          $ref: '#/components/responses/Conflict'
        '413':
          $ref: '#/components/responses/PayloadTooLarge'
        '415':
          $ref: '#/components/responses/UnsupportedMediaType'
        '422':
          $ref: '#/components/responses/UnprocessableContent'
        '429':
          $ref: '#/components/responses/BulkRateLimited'
        '500':
          $ref: '#/components/responses/InternalServerError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
        default:
          $ref: '#/components/responses/Error'
      security:
        - apiKey:
            - crm:write
components:
  schemas:
    CompanyBulkUpsertRequest:
      type: object
      properties:
        items:
          minItems: 1
          maxItems: 100
          type: array
          items:
            $ref: '#/components/schemas/CompanyUpsertRequest'
          description: >-
            The companies, each as `companies.upsert` takes it, 1 to 100. The
            whole body is checked first: one malformed item refuses the request
            with 422 `validation_error` at its path, such as `items.3.name`, and
            nothing is written.
      required:
        - items
      additionalProperties: false
      description: Up to 100 companies to create or update by domain.
    CompanyBulkWriteResult:
      type: object
      properties:
        results:
          type: array
          items:
            oneOf:
              - $ref: '#/components/schemas/CompanyBulkItemWritten'
              - $ref: '#/components/schemas/BulkItemFailed'
          description: One result per item, in the order of `items`.
        created:
          type: integer
          minimum: -9007199254740991
          maximum: 9007199254740991
          description: How many items created a record.
        updated:
          type: integer
          minimum: -9007199254740991
          maximum: 9007199254740991
          description: How many items updated a record.
        failed:
          type: integer
          minimum: -9007199254740991
          maximum: 9007199254740991
          description: How many items failed.
      required:
        - results
        - created
        - updated
        - failed
      additionalProperties: true
      description: What a bulk write did, item by item.
    CompanyUpsertRequest:
      type: object
      properties:
        domain:
          description: >-
            The key: the company’s domain, such as `example.com`; a URL is
            reduced to its host. The live company with this domain is updated,
            or a company is created when there is none.
          type: string
        name:
          description: >-
            The company’s name, 1 to 120 characters. Required when the company
            is created.
          type: string
          minLength: 1
          maxLength: 120
        website:
          description: >-
            The website address; blank means none. `domain` is not derived from
            it.
          type: string
          maxLength: 2048
        industry:
          description: The industry, at most 255 characters.
          anyOf:
            - type: string
              maxLength: 255
            - type: 'null'
        employeeCount:
          description: How many people the company employs.
          anyOf:
            - type: integer
              minimum: 0
              maximum: 2147483647
            - type: 'null'
        annualRevenue:
          description: The annual revenue, with at most two decimals.
          anyOf:
            - type: number
              minimum: 0
              maximum: 999999999999.99
            - type: 'null'
        linkedinUrl:
          description: The LinkedIn page address; blank means none.
          type: string
          maxLength: 2048
        country:
          description: The country, as free text; blank means none.
          type: string
          maxLength: 120
        summary:
          description: A short description of the company.
          anyOf:
            - type: string
              maxLength: 5000
            - type: 'null'
        city:
          description: The city the company is based in.
          anyOf:
            - type: string
              maxLength: 255
            - type: 'null'
        legalForm:
          description: The legal form, such as `GmbH`.
          anyOf:
            - type: string
              maxLength: 255
            - type: 'null'
        registerNumber:
          description: The commercial register number.
          anyOf:
            - type: string
              maxLength: 255
            - type: 'null'
        ownerUserId:
          description: >-
            The member who owns the company, by user id. List the members, and
            their ids, with `GET /v1/workspace-members` (needs `crm:write`).
          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})$
        address:
          description: >-
            The postal address, as an object of your choosing; it replaces the
            whole address.
          type: object
          propertyNames:
            type: string
          additionalProperties: {}
        customFields:
          description: >-
            Custom field values by key, checked against the workspace’s company
            custom fields; the keys left out keep their values.
          type: object
          propertyNames:
            type: string
          additionalProperties: {}
      required:
        - domain
      additionalProperties: false
      description: >-
        A company to create or update, found by its `domain`. A field left out
        keeps its value; `name` is required when the company is created.
    CompanyBulkItemWritten:
      type: object
      properties:
        index:
          type: integer
          minimum: -9007199254740991
          maximum: 9007199254740991
          description: The item’s position in `items`, from 0.
        outcome:
          type: string
          enum:
            - created
            - updated
          description: >-
            `created` when the item created the company; `updated` when the
            fields sent were written to an existing one. A bulk upsert creates
            when no live company had the domain; a bulk create only creates and
            a bulk update only updates.
        company:
          $ref: '#/components/schemas/Company'
          description: The company as it is now.
      required:
        - index
        - outcome
        - company
      additionalProperties: true
      description: A company a bulk write created or updated.
    BulkItemFailed:
      type: object
      properties:
        index:
          type: integer
          minimum: -9007199254740991
          maximum: 9007199254740991
          description: The item’s position in `items`, from 0.
        outcome:
          type: string
          const: failed
          description: The item was not written; nothing changed for it.
        error:
          $ref: '#/components/schemas/ErrorInfo'
          description: >-
            Why, as the error envelope says it: the `code`, `message` and
            `details` the single call would have answered for this item, and the
            request’s `requestId`.
      required:
        - index
        - outcome
        - error
      additionalProperties: true
      description: A bulk item that failed on its own.
    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.
    Company:
      type: object
      properties:
        id:
          type: string
          description: The company’s id.
        workspaceId:
          type: string
          description: The workspace the company belongs to.
        name:
          type: string
          description: The company’s name.
        domain:
          description: The company’s domain, such as `example.com`.
          type:
            - string
            - 'null'
        website:
          description: The website address.
          type:
            - string
            - 'null'
        industry:
          description: The industry.
          type:
            - string
            - 'null'
        employeeCount:
          anyOf:
            - type: integer
              minimum: -9007199254740991
              maximum: 9007199254740991
            - type: 'null'
          description: How many people the company employs.
        annualRevenue:
          description: The annual revenue.
          type:
            - number
            - 'null'
        address:
          type: object
          propertyNames:
            type: string
          additionalProperties: {}
          description: The postal address, as it was given.
        linkedinUrl:
          description: The LinkedIn page address.
          type:
            - string
            - 'null'
        country:
          description: The country.
          type:
            - string
            - 'null'
        summary:
          description: A short description of the company.
          type:
            - string
            - 'null'
        city:
          description: The city the company is based in.
          type:
            - string
            - 'null'
        legalForm:
          description: The legal form, such as `GmbH`.
          type:
            - string
            - 'null'
        registerNumber:
          description: The commercial register number.
          type:
            - string
            - 'null'
        buildingEnergyTags:
          description: Building-energy markets the company is known to work in. Read-only.
          anyOf:
            - type: array
              items:
                type: string
            - type: 'null'
        ownerUserId:
          description: >-
            The member who owns the company, by user id. List the members, and
            their ids, with `GET /v1/workspace-members` (needs `crm:write`).
          type:
            - string
            - 'null'
        customFields:
          type: object
          propertyNames:
            type: string
          additionalProperties: {}
          description: Custom field values, by the custom field’s key.
        canonicalCompanyId:
          description: >-
            The Enrik Data company this one is linked to; `null` when it is not.
            Read-only.
          type:
            - string
            - 'null'
        enrikUpdateAvailable:
          description: >-
            Whether Enrik Data has newer facts about the company than this
            workspace applied.
          type: boolean
        enrikSnapshotVersion:
          description: The Enrik Data version the company’s facts were last taken from.
          type:
            - string
            - 'null'
        createdBy:
          description: The user who created the company; `null` when an API key did.
          type:
            - string
            - 'null'
        updatedBy:
          description: The user who changed the company last.
          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 company was created.
        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 company last changed. Send it back as `expectedUpdatedAt`
            to update safely.
        deletedAt:
          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 was deleted; `null` while it is live.
        signalSummary:
          anyOf:
            - $ref: '#/components/schemas/CompanySignalSummary'
            - type: 'null'
          description: >-
            What the company’s active signals add up to: set on a list page,
            `null` elsewhere and for a company with no signals.
        enrichmentCells:
          description: >-
            With `include=enrichmentCells`: each enrichment column’s state for
            this record, by column id.
          type: object
          propertyNames:
            type: string
          additionalProperties:
            $ref: '#/components/schemas/EnrichmentColumnCell'
        formulaCells:
          description: >-
            With `include=formulaCells`: each formula column’s state, by column
            id.
          type: object
          propertyNames:
            type: string
          additionalProperties:
            $ref: '#/components/schemas/FormulaColumnCell'
        customApiCells:
          description: >-
            With `include=customApiCells`: each custom-API column’s state, by
            column id.
          type: object
          propertyNames:
            type: string
          additionalProperties:
            $ref: '#/components/schemas/CustomApiColumnCell'
        agentCells:
          description: 'With `include=agentCells`: each agent column’s state, by column id.'
          type: object
          propertyNames:
            type: string
          additionalProperties:
            $ref: '#/components/schemas/AgentColumnCell'
      required:
        - id
        - workspaceId
        - name
        - domain
        - website
        - industry
        - employeeCount
        - annualRevenue
        - address
        - linkedinUrl
        - country
        - ownerUserId
        - customFields
        - createdBy
        - updatedBy
        - createdAt
        - updatedAt
        - deletedAt
        - signalSummary
      additionalProperties: true
      description: An organisation in your workspace.
    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.
    CompanySignalSummary:
      type: object
      properties:
        companyId:
          type: string
          description: The company the summary is of.
        latestSignalTitle:
          description: The title of the latest active signal.
          type:
            - string
            - 'null'
        latestSignalCategory:
          anyOf:
            - type: string
              enum:
                - hiring
                - expansion
                - new_location
                - product_launch
                - event_participation
                - certification
                - partnership
                - technology
                - website_change
                - regulatory
                - leadership_change
                - funding
                - content_activity
                - customer_reference
                - other
            - type: 'null'
          description: >-
            The latest active signal’s category. What kind of signal it is, such
            as `hiring` or `funding`.
        latestSignalDate:
          description: When the latest active signal happened, as a date (`YYYY-MM-DD`).
          type:
            - string
            - 'null'
        latestSignalStrength:
          anyOf:
            - type: string
              enum:
                - weak
                - medium
                - strong
            - type: 'null'
          description: 'The latest active signal’s strength: `weak`, `medium` or `strong`.'
        latestSignalConfidence:
          anyOf:
            - type: string
              enum:
                - low
                - medium
                - high
            - type: 'null'
          description: 'How sure the latest active signal is: `low`, `medium` or `high`.'
        latestSignalRelevanceScore:
          anyOf:
            - type: integer
              minimum: -9007199254740991
              maximum: 9007199254740991
            - type: 'null'
          description: The latest active signal’s relevance, 0 to 100.
        activeSignalCount:
          type: integer
          minimum: -9007199254740991
          maximum: 9007199254740991
          description: How many active signals the company has.
        strongSignalCount:
          type: integer
          minimum: -9007199254740991
          maximum: 9007199254740991
          description: How many of them are strong.
        signalPriorityScore:
          anyOf:
            - type: integer
              minimum: -9007199254740991
              maximum: 9007199254740991
            - type: 'null'
          description: The highest relevance among the active signals, 0 to 100.
        scoringVersion:
          type: string
          description: The scoring rules the scores were computed under.
      required:
        - companyId
        - latestSignalTitle
        - latestSignalCategory
        - latestSignalDate
        - latestSignalStrength
        - latestSignalConfidence
        - latestSignalRelevanceScore
        - activeSignalCount
        - strongSignalCount
        - signalPriorityScore
        - scoringVersion
      additionalProperties: true
      description: What a company’s active signals add up to.
    EnrichmentColumnCell:
      type: object
      properties:
        definitionId:
          type: string
          description: The column’s id.
        fieldId:
          type: string
          description: The custom field the column writes its value into.
        status:
          type: string
          enum:
            - empty
            - queued
            - running
            - succeeded
            - failed
            - skipped
            - stale
          description: >-
            Where the cell stands: `empty`, `queued`, `running`, `succeeded`,
            `failed`, `skipped` or `stale`.
        lastErrorCode:
          description: >-
            Why the last attempt failed, as a stable code; `null` when it did
            not.
          type:
            - string
            - 'null'
        lastAppliedAt:
          description: >-
            When a value was last written into the field, as an ISO 8601
            instant.
          type:
            - string
            - 'null'
        latestRunId:
          description: The run that last worked on this cell; `null` when none has.
          type:
            - string
            - 'null'
      required:
        - definitionId
        - fieldId
        - status
        - lastErrorCode
        - lastAppliedAt
        - latestRunId
      additionalProperties: true
      description: >-
        The state of one enrichment column for one record. The value is in its
        field.
    FormulaColumnCell:
      type: object
      properties:
        definitionId:
          type: string
          description: The column’s id.
        fieldId:
          type: string
          description: The custom field the column writes its value into.
        status:
          type: string
          enum:
            - empty
            - queued
            - running
            - succeeded
            - failed
            - skipped
            - stale
          description: >-
            Where the cell stands: `empty`, `queued`, `running`, `succeeded`,
            `failed`, `skipped` or `stale`.
        lastErrorCode:
          description: >-
            Why the last attempt failed, as a stable code; `null` when it did
            not.
          type:
            - string
            - 'null'
        lastAppliedAt:
          description: >-
            When a value was last written into the field, as an ISO 8601
            instant.
          type:
            - string
            - 'null'
      required:
        - definitionId
        - fieldId
        - status
        - lastErrorCode
        - lastAppliedAt
      additionalProperties: true
      description: >-
        The state of one formula column for one record. The value is in its
        field.
    CustomApiColumnCell:
      type: object
      properties:
        definitionId:
          type: string
          description: The column’s id.
        fieldId:
          type: string
          description: The custom field the column writes its value into.
        status:
          type: string
          enum:
            - empty
            - queued
            - running
            - succeeded
            - failed
            - skipped
            - stale
          description: >-
            Where the cell stands: `empty`, `queued`, `running`, `succeeded`,
            `failed`, `skipped` or `stale`.
        lastErrorCode:
          description: >-
            Why the last attempt failed, as a stable code; `null` when it did
            not.
          type:
            - string
            - 'null'
        lastAppliedAt:
          description: >-
            When a value was last written into the field, as an ISO 8601
            instant.
          type:
            - string
            - 'null'
        latestRunId:
          description: The run that last worked on this cell; `null` when none has.
          type:
            - string
            - 'null'
      required:
        - definitionId
        - fieldId
        - status
        - lastErrorCode
        - lastAppliedAt
        - latestRunId
      additionalProperties: true
      description: >-
        The state of one custom-API column for one record. The value is in its
        field.
    AgentColumnCell:
      type: object
      properties:
        definitionId:
          type: string
          description: The column’s id.
        fieldId:
          type: string
          description: The custom field the column writes its value into.
        status:
          type: string
          enum:
            - empty
            - queued
            - running
            - succeeded
            - failed
            - skipped
            - stale
          description: >-
            Where the cell stands: `empty`, `queued`, `running`, `succeeded`,
            `failed`, `skipped` or `stale`.
        lastErrorCode:
          description: >-
            Why the last attempt failed, as a stable code; `null` when it did
            not.
          type:
            - string
            - 'null'
        lastAppliedAt:
          description: >-
            When a value was last written into the field, as an ISO 8601
            instant.
          type:
            - string
            - 'null'
        latestRunId:
          description: The run that last worked on this cell; `null` when none has.
          type:
            - string
            - 'null'
      required:
        - definitionId
        - fieldId
        - status
        - lastErrorCode
        - lastAppliedAt
        - latestRunId
      additionalProperties: true
      description: The state of one agent column for one record. The value is in its field.
  headers:
    BulkRateLimit:
      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. This operation writes many records in one request, so
        two policies count it: `api-key`, every request the key makes, and
        `api-key-bulk`, every request to a bulk operation.
      schema:
        type: string
      example: '"api-key";r=599;t=60, "api-key-bulk";r=29;t=60'
    BulkRateLimitPolicy:
      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.
        This operation writes many records in one request, so two policies count
        it: `api-key`, every request the key makes, and `api-key-bulk`, every
        request to a bulk operation.
      schema:
        type: string
      example: '"api-key";q=600;w=60, "api-key-bulk";q=30;w=60'
    RetryAfter:
      description: >-
        Seconds to wait before retrying. It takes priority over the `t` of every
        `RateLimit` item.
      schema:
        type: integer
        minimum: 1
      example: 60
  responses:
    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
    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
    PayloadTooLarge:
      description: >-
        The body is over the size limit. Branch on `error.code`; quote
        `error.requestId` to support.


        The codes a public operation answers with it:


        - `payload_too_large`: The body is over the size limit, currently 1 MiB.
        Send a smaller body.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: payload_too_large
              message: Payload Too Large
              requestId: 5b1d3c1e-8d6f-4f2a-9a57-3a9b1f2c7d10
    UnsupportedMediaType:
      description: >-
        The body’s media type cannot be read. Branch on `error.code`; quote
        `error.requestId` to support.


        The codes a public operation answers with it:


        - `unsupported_media_type`: The `Content-Type` header is not a media
        type. Send `Content-Type: application/json`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: unsupported_media_type
              message: Unsupported Media Type
              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
    BulkRateLimited:
      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/BulkRateLimit'
        RateLimit-Policy:
          $ref: '#/components/headers/BulkRateLimitPolicy'
      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.