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

# Update assets in a batch

> Updates up to 100 `CUSTOM` or `INFORMATION` assets in one request, each with its own values. Each record is saved on its own, so one invalid record doesn't stop the others. The response is 200 with one result per record, in request order. An unknown `id` fails with `not_found`. Any other asset (a computer, cloud resource or employee) fails with `resource_not_writable`.

Records follow the bulk edit rules of the Secfix app. Some fields can't be bulk-edited in some categories: the field isn't configured for the category, a Secfix tag sets it, or it's marked not editable. This can include `classification`. Such a field is skipped and listed in `skippedFields`, and the other fields are saved, so the record is still `SUCCESS`. If every change in a record is skipped, nothing is saved and the record fails with `not_editable`. The single-asset `PATCH` rejects such a field with `validation_failed` instead.

`tags` aren't supported in a batch; use the single-asset `PATCH`. Each `id` can appear only once. A batch counts as one write request for rate limiting. Requires the `all:write` scope.



## OpenAPI

````yaml /api-reference/openapi.yaml patch /v1/inventory/assets/batch-update
openapi: 3.0.1
info:
  title: Secfix Public API
  description: >-
    Read and manage your Secfix compliance data from your own systems. Get an
    access token from `POST /oauth/token` with the OAuth 2.0 client credentials
    grant, then send it as a bearer token to the `/v1` endpoints. Errors are
    JSON objects with a stable `code` and the `requestId`. Lists use cursor
    pagination.
  contact:
    name: Secfix Support
    url: https://secfix.com
    email: support@secfix.com
  license:
    name: Proprietary
    url: https://secfix.com/license
  version: 1.0.0
servers:
  - url: https://api.secfix.com
    description: Production
  - url: https://api-staging.secfix.com
    description: Staging
security:
  - bearerAuth: []
tags:
  - name: Employees
    description: >-
      Read the people in your workspace, with their employment status, group and
      onboarding progress.
  - name: Inventory
    description: >-
      Read assets in every inventory category. Create, update and delete
      `CUSTOM` and `INFORMATION` assets.
  - name: OAuth
    description: Get an access token with the OAuth 2.0 client credentials grant.
  - name: Groups
    description: >-
      Read employee groups, their member counts and the onboarding tasks
      assigned to them.
  - name: Health
    description: Check that the API is up.
  - name: Computers
    description: Read the computers in your workspace and their security settings.
paths:
  /v1/inventory/assets/batch-update:
    patch:
      tags:
        - Inventory
      summary: Update assets in a batch
      description: >-
        Updates up to 100 `CUSTOM` or `INFORMATION` assets in one request, each
        with its own values. Each record is saved on its own, so one invalid
        record doesn't stop the others. The response is 200 with one result per
        record, in request order. An unknown `id` fails with `not_found`. Any
        other asset (a computer, cloud resource or employee) fails with
        `resource_not_writable`.


        Records follow the bulk edit rules of the Secfix app. Some fields can't
        be bulk-edited in some categories: the field isn't configured for the
        category, a Secfix tag sets it, or it's marked not editable. This can
        include `classification`. Such a field is skipped and listed in
        `skippedFields`, and the other fields are saved, so the record is still
        `SUCCESS`. If every change in a record is skipped, nothing is saved and
        the record fails with `not_editable`. The single-asset `PATCH` rejects
        such a field with `validation_failed` instead.


        `tags` aren't supported in a batch; use the single-asset `PATCH`. Each
        `id` can appear only once. A batch counts as one write request for rate
        limiting. Requires the `all:write` scope.
      operationId: updateAssetsBatch
      parameters:
        - name: Idempotency-Key
          in: header
          description: >-
            A unique key, up to 256 characters, that makes the request safe to
            retry. Use a new UUID for each distinct request. If you send the
            same key again, you get the first response back, for at least 24
            hours after the first request completes. Only successful (2xx)
            responses are stored. If the first request is still running, you get
            `409 idempotency_in_progress`: wait the number of seconds in
            `Retry-After`, then retry. See [Idempotency](/idempotency).
          required: true
          schema:
            maxLength: 256
            type: string
            example: b0f8e5a2-3c1d-4e6f-8a9b-0c1d2e3f4a5b
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BatchAssetUpdateRequest'
        required: true
      responses:
        '200':
          description: >-
            Every record was processed. Check `status` on each entry in
            `results`; each entry has the record's `index`. Resend only the
            failed records, with a new `Idempotency-Key`.
          headers:
            X-RateLimit-Limit:
              description: Requests allowed in the current rate-limit window.
              style: simple
              schema:
                type: integer
            X-RateLimit-Remaining:
              description: Requests remaining in the current rate-limit window.
              style: simple
              schema:
                type: integer
            X-RateLimit-Reset:
              description: Seconds until the rate-limit window resets.
              style: simple
              schema:
                type: integer
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BatchResponse'
        '400':
          description: >-
            The request is invalid: `records` is missing, empty or has more than
            100 entries, an `id` appears twice, or the `Idempotency-Key` header
            is missing or longer than 256 characters. Code: `validation_failed`
            or `malformed_request`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProblemDetail'
        '401':
          description: >-
            The access token is missing, invalid or replaced by a newer one.
            Code: `unauthorized` or `token_superseded`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProblemDetail'
        '403':
          description: >-
            The access token doesn't have the scope this endpoint needs. Code:
            `scope_required`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProblemDetail'
        '405':
          description: >-
            This path doesn't support the HTTP method. The `Allow` header lists
            the methods it supports. Code: `method_not_allowed`.
          headers:
            Allow:
              description: Comma-separated list of the HTTP methods this path supports.
              style: simple
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProblemDetail'
        '409':
          description: >-
            The `Idempotency-Key` was already used with a different body
            (`idempotency_conflict`), or the first request with this key is
            still running (`idempotency_in_progress`). For
            `idempotency_in_progress`, retry after `Retry-After`.
          headers:
            Retry-After:
              description: >-
                Seconds to wait before retrying. Sent with
                `idempotency_in_progress`. A `write_conflict` on one record is
                reported in that record's result, not as a 409.
              style: simple
              schema:
                type: integer
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProblemDetail'
        '413':
          description: 'The request body is too large. Code: `payload_too_large`.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProblemDetail'
        '415':
          description: >-
            Send the request body as `application/json`. Code:
            `unsupported_media_type`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProblemDetail'
        '429':
          description: >-
            Too many requests. Wait the number of seconds in `Retry-After`, then
            retry. Code: `rate_limited`.
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              style: simple
              schema:
                type: integer
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProblemDetail'
        '500':
          description: 'Unexpected server error. Code: `internal_error`.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProblemDetail'
components:
  schemas:
    BatchAssetUpdateRequest:
      required:
        - records
      type: object
      properties:
        records:
          maxItems: 100
          minItems: 1
          type: array
          description: The assets to update, 1-100. Each `id` can appear only once.
          items:
            $ref: '#/components/schemas/BatchAssetUpdateRecord'
      description: >-
        Updates up to 100 `CUSTOM` or `INFORMATION` assets, each with its own
        values. `tags` are only supported by the single-asset `PATCH`.
    BatchResponse:
      type: object
      properties:
        results:
          type: array
          description: One result per record, in request order.
          items:
            $ref: '#/components/schemas/BatchItemResult'
      description: >-
        Results of a batch request, one per record. The response is 200 even
        when some or all records failed. Resend only the failed records, with a
        new `Idempotency-Key`.
    ProblemDetail:
      type: object
      properties:
        code:
          type: string
          description: >-
            Error code for your error handling. It doesn't change between
            releases.
          example: not_found
        detail:
          type: string
          description: What went wrong in this request.
          example: No asset found for the given id.
        instance:
          type: string
          description: URI that identifies this occurrence of the error.
          example: /v1/inventory/assets/3f1c9a2e-8b4d-4e7a-9c1f-2a5b6c7d8e9f
        requestId:
          type: string
          description: >-
            The request's id, also sent in the `X-Request-Id` header. Include it
            when you contact support.
          example: req_01HZY8Q3M4N5P6R7S8T9V0W1X2
        status:
          type: integer
          description: HTTP status code.
          format: int32
          example: 404
        title:
          type: string
          description: Short summary of the error type.
          example: Not Found
        type:
          type: string
          description: URI that identifies the error type.
          example: https://api.secfix.com/problems/not_found
      description: The JSON body of every error response.
    BatchAssetUpdateRecord:
      required:
        - id
      type: object
      properties:
        classification:
          type: string
          description: >-
            Data classification: `RESTRICTED`, `CONFIDENTIAL`, `INTERNAL`,
            `PUBLIC` or `UNKNOWN`, in any letter case.
          example: CONFIDENTIAL
        customIdentifier:
          maxLength: 255
          minLength: 0
          type: string
          description: >-
            Serial number or asset ID, shown in Secfix as **ID/Serial No.** Up
            to 255 characters. You can't change `externalSource` or
            `externalAssetId`; they're set on create.
          example: SN-12345
        dataStored:
          $ref: '#/components/schemas/DataStoredInput'
        description:
          maxLength: 500
          minLength: 0
          type: string
          description: Asset description, up to 500 characters.
          example: Primary production web server.
        id:
          type: string
          description: The `id` of the asset to update.
          format: uuid
          example: 3f1c9a2e-8b4d-4e7a-9c1f-2a5b6c7d8e9f
        name:
          maxLength: 255
          minLength: 0
          type: string
          description: >-
            New asset name, 1-255 characters. Leading and trailing spaces are
            removed, and a blank name is rejected.
          example: Finance laptop pool
        ownerEmail:
          maxLength: 320
          minLength: 0
          type: string
          description: >-
            New owner's email address, instead of `ownerId`. Case-insensitive.
            Must belong to an active employee in your workspace who is included
            in compliance.
          example: jane.doe@example.com
        ownerId:
          type: string
          description: New owner's employee `id`.
          format: uuid
          example: a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d
        tags:
          maxItems: 20
          minItems: 0
          type: array
          description: >-
            Your workspace's tags to set on the asset. Tags you leave out are
            removed. Each `key` must be a tag key that exists in your workspace;
            an unknown key is rejected. Tags managed by Secfix are read-only and
            stay as they are, so you don't need to send them. Single-asset
            `PATCH` only; not supported in a batch.
          items:
            $ref: '#/components/schemas/TagDto'
      description: >-
        One asset to update: its `id` and the fields to change. Only `CUSTOM`
        and `INFORMATION` assets can be updated. `tags` aren't supported in a
        batch.
    BatchItemResult:
      type: object
      properties:
        action:
          type: string
          description: 'For a successful create: whether the asset was created or updated.'
          enum:
            - CREATED
            - UPDATED
        code:
          type: string
          description: Why the record failed. Only set when it failed.
          example: validation_failed
          enum:
            - validation_failed
            - resource_not_writable
            - not_editable
            - not_found
            - write_conflict
            - internal_error
        field:
          type: string
          description: >-
            The request field that failed validation. Only set for
            `validation_failed`.
          example: ownerEmail
        id:
          type: string
          description: >-
            For a create, the `id` of the new or matched asset; left out when
            the create failed. For a delete or update, the `id` you sent.
          format: uuid
        index:
          type: integer
          description: Position of the record in `records`, starting at 0.
          format: int32
          example: 0
        message:
          type: string
          description: Short explanation of the failure. Only set when the record failed.
          example: unknown owner
        skippedFields:
          type: array
          description: >-
            Batch updates only. Fields you sent that weren't changed, because
            the asset's category doesn't allow bulk editing them: the field
            isn't configured, a Secfix tag sets it, or it's marked not editable.
            On a `SUCCESS` record the other fields were saved; on a
            `not_editable` record nothing was. Left out when every change was
            applied.
          items:
            type: string
            example: description
        status:
          type: string
          description: Outcome of the record.
          enum:
            - SUCCESS
            - ERROR
      description: The result of one record in a batch.
    DataStoredInput:
      type: object
      properties:
        containsPatientData:
          type: boolean
          description: Whether the asset stores patient data.
          example: false
        containsUserData:
          type: boolean
          description: Whether the asset stores user data.
          example: true
        userDataInfo:
          maxLength: 500
          minLength: 0
          type: string
          description: What kind of user data the asset stores, up to 500 characters.
          example: Customer names and email addresses.
      description: What data the asset stores. On create, fields you leave out stay unset.
    TagDto:
      type: object
      properties:
        key:
          maxLength: 1000
          minLength: 0
          type: string
          description: >-
            Tag key. On writes, it must be a tag key that exists in your
            workspace.
          example: environment
        readOnly:
          type: boolean
          description: >-
            `true` for tags managed by Secfix, such as `SecfixOwner`. You can't
            change those through the API. Ignored on writes.
          readOnly: true
          example: false
        value:
          maxLength: 255
          minLength: 0
          type: string
          description: Tag value.
          example: production
      description: >-
        A tag on an asset. On writes, `key` must be a tag key in your workspace
        that you can edit.
  securitySchemes:
    bearerAuth:
      type: http
      description: Access token from `POST /oauth/token`.
      scheme: bearer
      bearerFormat: JWT

````

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