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

# Create or update one asset

> Writes one asset. The service forwards the request body to the ingest service and returns its status, content type and body unchanged: 201 when the asset was created, 200 when it was updated.

With `objectData` the ingest service decides by identity matching whether the asset already exists. Without `objectData`, `object.id` is required and the asset is updated.

Requires the scope `api_write` (*Read and Write*). Errors of the ingest service are not `application/problem+json`: they carry `errorMessage` (400) or, for a server fault, the same body with status 500.




## OpenAPI

````yaml /api-reference/openapi.en.yaml post /asset
openapi: 3.0.3
info:
  title: Docusnap365 REST API
  version: v1
  description: >
    The public REST API of Docusnap365 for reading, querying and writing assets.


    **Request flow.** Every request passes these checks in this order: the API
    key (401 if it is missing or invalid), the rights of the key (403 if it
    lacks the right for the operation), the request quota (429, or 503 when the
    quota cannot be checked), then the operation itself. You grant the rights
    when you create the API key under *Administration › Integrations › API
    Keys*: *Read* (`api_read`) or *Read and Write* (`api_write`).


    **Request quota.** Every call to one of the operations counts as one
    request. The quota is shared with the MCP server of the same subscription.
    Once a request has been counted, the `X-RateLimit-*` headers accompany the
    response, including error responses; a subscription without a limit gets
    none.


    **Errors.** Errors are `application/problem+json` (RFC 9457) with the
    members `type`, `title`, `status`, `detail`, `instance`, `errorCode`,
    `traceId` and `errors`. Do not parse `detail`. There are two exceptions: the
    answer 401 has neither a body nor a Content-Type, even when the API key is
    missing; and on the write path an error of the ingest service is returned
    unchanged and carries `errorMessage` instead.
servers:
  - url: https://api.docusnap365.com/api/v1
security:
  - ApiKeyAuth: []
tags:
  - name: Assets
    description: Read and write single assets.
  - name: Query
    description: Query assets with filter, sort, expands and paging.
paths:
  /asset:
    post:
      tags:
        - Assets
      summary: Create or update one asset
      description: >
        Writes one asset. The service forwards the request body to the ingest
        service and returns its status, content type and body unchanged: 201
        when the asset was created, 200 when it was updated.


        With `objectData` the ingest service decides by identity matching
        whether the asset already exists. Without `objectData`, `object.id` is
        required and the asset is updated.


        Requires the scope `api_write` (*Read and Write*). Errors of the ingest
        service are not `application/problem+json`: they carry `errorMessage`
        (400) or, for a server fault, the same body with status 500.
      operationId: ingestAsset
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AssetBundle'
            examples:
              An asset with a name and a type:
                value:
                  schemaId: 9b2f6a52-1c0e-4c5a-8d55-5f0f6a3f7a11
                  object:
                    name: Server01
                    schemaId: 9b2f6a52-1c0e-4c5a-8d55-5f0f6a3f7a11
      responses:
        '200':
          description: The asset was updated.
          headers:
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Extra-Remaining:
              $ref: '#/components/headers/X-RateLimit-Extra-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ObjectsApiResult'
        '201':
          description: The asset was created.
          headers:
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Extra-Remaining:
              $ref: '#/components/headers/X-RateLimit-Extra-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ObjectsApiResult'
        '400':
          description: >
            The request is rejected. Two body shapes exist: the ingest service
            answers with an `ObjectsApiResult` whose `errorMessage` names the
            reason (missing `object`, missing or too long name, missing
            `object.id`, protected asset, too few identity values); a body that
            cannot be read is answered by this service as
            `application/problem+json` with `errorCode` `VALIDATION_FAILED`.
          x-error-codes:
            - VALIDATION_FAILED
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ObjectsApiResult'
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/ForbiddenWrite'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          description: >-
            A server fault. The ingest service answers with an
            `ObjectsApiResult`; every other fault is `application/problem+json`
            with `errorCode` `INTERNAL_ERROR`.
          x-error-codes:
            - INTERNAL_ERROR
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ObjectsApiResult'
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
components:
  schemas:
    AssetBundle:
      title: Asset with data
      type: object
      required:
        - schemaId
      properties:
        id:
          type: string
          format: uuid
          description: >-
            A correlation id of this asset in the request. The ingest service
            reports its result under it (`idPair.fakeId`). A new GUID by
            default.
        schemaId:
          type: string
          format: uuid
          description: The type of the asset.
        object:
          $ref: '#/components/schemas/AssetCore'
        objectData:
          description: >-
            The data of the asset as JSON, structured by the type. Needed for
            identity matching.
        essentials:
          $ref: '#/components/schemas/EssentialsBundle'
        facets:
          type: object
          additionalProperties:
            type: array
            items: {}
          description: Further data by name, each a list of JSON values.
    ObjectsApiResult:
      title: Result of a write
      type: object
      description: >-
        The answer of the ingest service for one asset. Properties without a
        value are omitted.
      properties:
        id:
          type: string
          format: uuid
          description: The id of the asset.
        idPair:
          $ref: '#/components/schemas/IdPair'
        schemaId:
          type: string
          format: uuid
        previousSchemaId:
          type: string
          format: uuid
          description: The former type, when the update changed it.
        idMatchResponse:
          type: object
          additionalProperties: true
          description: The result of the identity matching.
        isCreate:
          type: boolean
          description: True when the asset was created.
        matchedObjectInRecycleBin:
          type: boolean
          description: True when a protected match is in the recycle bin.
        errorMessage:
          type: string
          description: The reason, as a technical English sentence. Present on a rejection.
        isSuccess:
          type: boolean
          description: True when `errorMessage` is empty.
    ProblemDetails:
      title: Problem details
      type: object
      description: >-
        An error according to RFC 9457. `errors` is never empty; for one error
        `errors[0].code` equals `errorCode`.
      properties:
        type:
          type: string
          description: >-
            A URN derived from `errorCode`, for example
            `urn:ds365:error:not-found`. It cannot be resolved.
        title:
          type: string
          description: A fixed English text per code.
        status:
          type: integer
          description: The HTTP status code.
        detail:
          type: string
          description: >-
            A technical English sentence. The text may change and should not be
            evaluated.
        instance:
          type: string
          description: The request path.
        errorCode:
          type: string
          description: >-
            The error code. The codes of an operation are listed in
            `x-error-codes` of its response.
        traceId:
          type: string
          description: The trace id of the request. Give it to support.
        errors:
          type: array
          items:
            $ref: '#/components/schemas/ProblemErrorItem'
    AssetCore:
      title: General details of the asset
      type: object
      properties:
        id:
          type: string
          format: uuid
          nullable: true
          description: Required to update an asset without `objectData`.
        schemaId:
          type: string
          format: uuid
          description: If empty, the `schemaId` of the enclosing `AssetBundle` is used.
        parentId:
          type: string
          format: uuid
          nullable: true
        name:
          type: string
          description: >-
            Required. Leading and trailing blanks are removed; at most 256
            characters.
        sourceType:
          type: string
          nullable: true
        completenessLevel:
          type: integer
          format: int32
          nullable: true
          description: >-
            How complete the record is. A more complete stored record is
            protected against overwriting by a poorer one; unset counts as 0.
        organizationId:
          type: string
          format: uuid
          nullable: true
        locationId:
          type: string
          format: uuid
          nullable: true
        platformId:
          type: string
          format: uuid
          nullable: true
        domainId:
          type: string
          format: uuid
          nullable: true
        version:
          type: integer
          format: int32
          default: 1
        status:
          type: string
          nullable: true
        createdAt:
          type: string
          format: date-time
        createdBy:
          type: string
          format: uuid
          nullable: true
        modifiedAt:
          type: string
          format: date-time
        modifiedBy:
          type: string
          format: uuid
          nullable: true
        deletedAt:
          type: string
          format: date-time
          nullable: true
        deletedBy:
          type: string
          format: uuid
          nullable: true
    EssentialsBundle:
      title: Essentials
      type: object
      properties:
        sections:
          type: object
          additionalProperties: {}
          description: The essentials by section name.
    IdPair:
      title: Id pair
      type: object
      properties:
        fakeId:
          type: string
          format: uuid
          description: The `id` of the body from the request.
        dbId:
          type: string
          format: uuid
          description: The id of the asset.
    ProblemErrorItem:
      title: Error item
      type: object
      required:
        - code
      properties:
        code:
          type: string
          description: The specific code of this item.
        path:
          type: string
          description: >-
            The field or parameter the error concerns. Absent when it concerns
            the whole request.
        data:
          type: object
          additionalProperties: true
          description: >-
            Further values, for example `entityType` and `id` of a missing asset
            or `missingScopes`. Absent when empty.
  headers:
    X-RateLimit-Limit:
      description: >-
        Requests included per quota period. Not sent for a subscription without
        a limit.
      schema:
        type: integer
    X-RateLimit-Remaining:
      description: Included plus extra requests still available in the running period.
      schema:
        type: integer
    X-RateLimit-Extra-Remaining:
      description: Extra requests still available. They are not reset with the period.
      schema:
        type: integer
    X-RateLimit-Reset:
      description: Start of the next quota period as Unix time in seconds.
      schema:
        type: integer
        format: int64
    Retry-After:
      description: >-
        Start of the next quota period as an HTTP date. The same instant as
        `X-RateLimit-Reset`.
      schema:
        type: string
  responses:
    Unauthorized:
      description: The API key is missing or invalid.
      x-error-codes:
        - UNAUTHORIZED
    ForbiddenWrite:
      description: >-
        The key lacks the scope `api_write` (*Read and Write*), or no scope was
        sent at all (then `detail` points to the API key and no `missingScopes`
        are given).
      x-error-codes:
        - FORBIDDEN
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
          examples:
            A key without the required scope:
              value:
                type: urn:ds365:error:forbidden
                title: Forbidden
                status: 403
                detail: 'Missing required scopes: api_write'
                instance: /api/v1/asset
                errorCode: FORBIDDEN
                traceId: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01
                errors:
                  - code: FORBIDDEN
                    data:
                      missingScopes:
                        - api_write
    TooManyRequests:
      description: >-
        The request quota of the subscription is used up, included and extra
        requests alike. Retry after the instant in `Retry-After`. A denied
        request is counted as well.
      x-error-codes:
        - REST_REQUEST_QUOTA_EXCEEDED
      headers:
        Retry-After:
          $ref: '#/components/headers/Retry-After'
        X-RateLimit-Limit:
          $ref: '#/components/headers/X-RateLimit-Limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/X-RateLimit-Remaining'
        X-RateLimit-Extra-Remaining:
          $ref: '#/components/headers/X-RateLimit-Extra-Remaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/X-RateLimit-Reset'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
          examples:
            The quota is used up:
              value:
                type: urn:ds365:error:rest-request-quota-exceeded
                title: Request quota exceeded
                status: 429
                detail: >-
                  The request quota of 10000 requests per period is exhausted
                  until 2026-12-01T00:00:00.0000000+00:00.
                instance: /api/v1/assets
                errorCode: REST_REQUEST_QUOTA_EXCEEDED
                traceId: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01
                errors:
                  - code: REST_REQUEST_QUOTA_EXCEEDED
                    data:
                      requestsLimit: 10000
                      requestsUsed: 10000
                      quotaResetAt: '2026-12-01T00:00:00+00:00'
    ServiceUnavailable:
      description: >-
        The request quota could not be checked and the request was therefore not
        served, or the database failed transiently. Retrying may succeed.
      x-error-codes:
        - SERVICE_UNAVAILABLE
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        The API key of the subscription. Each operation names the scope it needs
        in `x-pat-scopes`: `api_read` (in the interface *Read*) or `api_write`
        (*Read and Write*). The key is created under *Administration ›
        Integrations › API Keys*.

````

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