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

# Ein Asset anlegen oder aktualisieren

> Schreibt ein Asset. Der Dienst leitet den Anfragekörper an den Ingest-Dienst weiter und gibt dessen Status, Content-Type und Körper unverändert zurück: 201, wenn das Asset angelegt wurde, 200, wenn es aktualisiert wurde.

Mit `objectData` entscheidet der Ingest-Dienst über die Identitätszuordnung, ob das Asset schon besteht. Ohne `objectData` ist `object.id` Pflicht, und das Asset wird aktualisiert.

Braucht das Recht `api_write` (*Lesen und Schreiben*). Fehler des Ingest-Dienstes sind kein `application/problem+json`: Sie tragen `errorMessage` (400) oder bei einem Serverfehler denselben Körper mit Status 500.




## OpenAPI

````yaml /api-reference/openapi.de.yaml post /asset
openapi: 3.0.3
info:
  title: Docusnap365 REST-API
  version: v1
  description: >
    Die öffentliche REST-API von Docusnap365 zum Lesen, Abfragen und Schreiben
    von Assets.


    **Ablauf einer Anfrage.** Jede Anfrage durchläuft diese Prüfungen in dieser
    Reihenfolge: den API-Schlüssel (401, wenn er fehlt oder ungültig ist), die
    Rechte des Schlüssels (403, wenn ihm das Recht für die Operation fehlt), das
    Anfrage-Kontingent (429, oder 503, wenn das Kontingent nicht geprüft werden
    kann), danach die Operation selbst. Die Rechte vergeben Sie beim Anlegen des
    API-Schlüssels unter *Verwaltung › Integrationen › API-Schlüssel*: *Lesen*
    (`api_read`) oder *Lesen und Schreiben* (`api_write`).


    **Anfrage-Kontingent.** Jeder Aufruf einer Operation zählt als eine Anfrage.
    Das Kontingent teilt sich die Subscription mit dem MCP-Server. Sobald eine
    Anfrage gezählt ist, begleiten die `X-RateLimit-*`-Kopfzeilen die Antwort,
    auch eine Fehlerantwort; eine Subscription ohne Obergrenze bekommt keine.


    **Fehler.** Fehler sind `application/problem+json` (RFC 9457) mit den
    Feldern `type`, `title`, `status`, `detail`, `instance`, `errorCode`,
    `traceId` und `errors`. `detail` darf nicht ausgewertet werden. Ausnahmen:
    Die Antwort 401 hat weder Körper noch Content-Type, auch wenn der
    API-Schlüssel fehlt. Und auf dem Schreibweg wird ein Fehler des
    Ingest-Dienstes unverändert zurückgegeben und trägt stattdessen
    `errorMessage`.
servers:
  - url: https://api.docusnap365.com/api/v1
security:
  - ApiKeyAuth: []
tags:
  - name: Assets
    description: Einzelne Assets lesen und schreiben.
  - name: Query
    description: Assets mit Filter, Sortierung, Expands und seitenweiser Ausgabe abfragen.
paths:
  /asset:
    post:
      tags:
        - Assets
      summary: Ein Asset anlegen oder aktualisieren
      description: >
        Schreibt ein Asset. Der Dienst leitet den Anfragekörper an den
        Ingest-Dienst weiter und gibt dessen Status, Content-Type und Körper
        unverändert zurück: 201, wenn das Asset angelegt wurde, 200, wenn es
        aktualisiert wurde.


        Mit `objectData` entscheidet der Ingest-Dienst über die
        Identitätszuordnung, ob das Asset schon besteht. Ohne `objectData` ist
        `object.id` Pflicht, und das Asset wird aktualisiert.


        Braucht das Recht `api_write` (*Lesen und Schreiben*). Fehler des
        Ingest-Dienstes sind kein `application/problem+json`: Sie tragen
        `errorMessage` (400) oder bei einem Serverfehler denselben Körper mit
        Status 500.
      operationId: ingestAsset
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AssetBundle'
            examples:
              Ein Asset mit Name und Typ:
                value:
                  schemaId: 9b2f6a52-1c0e-4c5a-8d55-5f0f6a3f7a11
                  object:
                    name: Server01
                    schemaId: 9b2f6a52-1c0e-4c5a-8d55-5f0f6a3f7a11
      responses:
        '200':
          description: Das Asset wurde aktualisiert.
          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: Das Asset wurde angelegt.
          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: >
            Die Anfrage wird abgelehnt. Es gibt zwei Körperformen: Der
            Ingest-Dienst antwortet mit einem `ObjectsApiResult`, dessen
            `errorMessage` den Grund nennt (fehlendes `object`, fehlender oder
            zu langer Name, fehlende `object.id`, geschütztes Asset, zu wenige
            Identitätswerte); einen Körper, der sich nicht lesen lässt,
            beantwortet dieser Dienst als `application/problem+json` mit dem
            `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: >-
            Ein Serverfehler. Der Ingest-Dienst antwortet mit einem
            `ObjectsApiResult`; jeder andere Fehler ist
            `application/problem+json` mit dem `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 mit Daten
      type: object
      required:
        - schemaId
      properties:
        id:
          type: string
          format: uuid
          description: >-
            Eine Korrelations-Id dieses Assets in der Anfrage. Der Ingest-Dienst
            meldet sein Ergebnis darunter (`idPair.fakeId`). Standardmäßig eine
            neue GUID.
        schemaId:
          type: string
          format: uuid
          description: Der Typ des Assets.
        object:
          $ref: '#/components/schemas/AssetCore'
        objectData:
          description: >-
            Die Daten des Assets als JSON, gegliedert nach dem Typ. Für die
            Identitätszuordnung nötig.
        essentials:
          $ref: '#/components/schemas/EssentialsBundle'
        facets:
          type: object
          additionalProperties:
            type: array
            items: {}
          description: Weitere Daten nach Namen, jeweils eine Liste von JSON-Werten.
    ObjectsApiResult:
      title: Ergebnis eines Schreibens
      type: object
      description: >-
        Die Antwort des Ingest-Dienstes zu einem Asset. Eigenschaften ohne Wert
        fehlen.
      properties:
        id:
          type: string
          format: uuid
          description: Die Id des Assets.
        idPair:
          $ref: '#/components/schemas/IdPair'
        schemaId:
          type: string
          format: uuid
        previousSchemaId:
          type: string
          format: uuid
          description: Der frühere Typ, wenn die Aktualisierung sie geändert hat.
        idMatchResponse:
          type: object
          additionalProperties: true
          description: Das Ergebnis der Identitätszuordnung.
        isCreate:
          type: boolean
          description: Wahr, wenn das Asset angelegt wurde.
        matchedObjectInRecycleBin:
          type: boolean
          description: Wahr, wenn ein geschützter Treffer im Papierkorb liegt.
        errorMessage:
          type: string
          description: >-
            Der Grund als technischer englischer Satz. Bei einer Ablehnung
            vorhanden.
        isSuccess:
          type: boolean
          description: Wahr, wenn `errorMessage` leer ist.
    ProblemDetails:
      title: Problembeschreibung
      type: object
      description: >-
        Ein Fehler nach RFC 9457. `errors` ist nie leer; bei einem Fehler ist
        `errors[0].code` gleich `errorCode`.
      properties:
        type:
          type: string
          description: >-
            Ein URN, abgeleitet aus `errorCode`, zum Beispiel
            `urn:ds365:error:not-found`. Er lässt sich nicht auflösen.
        title:
          type: string
          description: Ein fester englischer Text je Code.
        status:
          type: integer
          description: Der HTTP-Statuscode.
        detail:
          type: string
          description: >-
            Ein technischer englischer Satz. Der Text kann sich ändern und soll
            nicht ausgewertet werden.
        instance:
          type: string
          description: Der Anfragepfad.
        errorCode:
          type: string
          description: >-
            Der Fehlercode. Die Codes einer Operation stehen in `x-error-codes`
            ihrer Antwort.
        traceId:
          type: string
          description: Die Trace-Id der Anfrage. Dem Support nennen.
        errors:
          type: array
          items:
            $ref: '#/components/schemas/ProblemErrorItem'
    AssetCore:
      title: Allgemeine Angaben des Assets
      type: object
      properties:
        id:
          type: string
          format: uuid
          nullable: true
          description: Nötig, um ein Asset ohne `objectData` zu aktualisieren.
        schemaId:
          type: string
          format: uuid
          description: Ist sie leer, gilt die `schemaId` des umgebenden `AssetBundle`.
        parentId:
          type: string
          format: uuid
          nullable: true
        name:
          type: string
          description: >-
            Pflicht. Leerzeichen am Anfang und Ende werden entfernt; höchstens
            256 Zeichen.
        sourceType:
          type: string
          nullable: true
        completenessLevel:
          type: integer
          format: int32
          nullable: true
          description: >-
            Wie vollständig der Datensatz ist. Ein vollständigerer gespeicherter
            Datensatz ist davor geschützt, von einem ärmeren überschrieben zu
            werden; ohne Angabe zählt 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: Die Essentials nach Abschnittsnamen.
    IdPair:
      title: Id-Paar
      type: object
      properties:
        fakeId:
          type: string
          format: uuid
          description: Die `id` des Körpers aus der Anfrage.
        dbId:
          type: string
          format: uuid
          description: Die Id des Assets.
    ProblemErrorItem:
      title: Fehlerelement
      type: object
      required:
        - code
      properties:
        code:
          type: string
          description: Der besondere Code dieses Elements.
        path:
          type: string
          description: >-
            Das Feld oder der Parameter, den der Fehler betrifft. Fehlt, wenn er
            die ganze Anfrage betrifft.
        data:
          type: object
          additionalProperties: true
          description: >-
            Weitere Werte, zum Beispiel `entityType` und `id` eines fehlenden
            Assets oder `missingScopes`. Fehlt, wenn leer.
  headers:
    X-RateLimit-Limit:
      description: >-
        Enthaltene Anfragen je Kontingentperiode. Wird für eine Subscription
        ohne Obergrenze nicht gesendet.
      schema:
        type: integer
    X-RateLimit-Remaining:
      description: >-
        Noch verfügbare enthaltene und zusätzliche Anfragen der laufenden
        Periode.
      schema:
        type: integer
    X-RateLimit-Extra-Remaining:
      description: >-
        Noch verfügbare zusätzliche Anfragen. Sie werden mit der Periode nicht
        zurückgesetzt.
      schema:
        type: integer
    X-RateLimit-Reset:
      description: Beginn der nächsten Kontingentperiode als Unix-Zeit in Sekunden.
      schema:
        type: integer
        format: int64
    Retry-After:
      description: >-
        Beginn der nächsten Kontingentperiode als HTTP-Datum. Derselbe Zeitpunkt
        wie `X-RateLimit-Reset`.
      schema:
        type: string
  responses:
    Unauthorized:
      description: Der API-Schlüssel fehlt oder ist ungültig.
      x-error-codes:
        - UNAUTHORIZED
    ForbiddenWrite:
      description: >-
        Dem Schlüssel fehlt das Recht `api_write` (*Lesen und Schreiben*), oder
        es wurde gar kein Recht gesendet (dann verweist `detail` auf den
        API-Schlüssel, und `missingScopes` fehlt).
      x-error-codes:
        - FORBIDDEN
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
          examples:
            Ein Schlüssel ohne das nötige Recht:
              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: >-
        Das Anfrage-Kontingent der Subscription ist aufgebraucht, enthaltene und
        zusätzliche Anfragen gleichermaßen. Wiederholen nach dem Zeitpunkt in
        `Retry-After`. Auch eine abgelehnte Anfrage wird gezählt.
      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:
            Das Kontingent ist aufgebraucht:
              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: >-
        Das Kontingent konnte nicht geprüft werden und die Anfrage wurde deshalb
        nicht bedient, oder die Datenbank ist vorübergehend ausgefallen. Ein
        erneuter Versuch kann gelingen.
      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: >-
        Der API-Schlüssel der Subscription. Jede Operation nennt in
        `x-pat-scopes` das Recht, das sie braucht: `api_read` (in der Oberfläche
        *Lesen*) oder `api_write` (*Lesen und Schreiben*). Der Schlüssel wird
        unter *Verwaltung › Integrationen › API-Schlüssel* angelegt.

````

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