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

# Assign users

> **Erforderliche Berechtigungen:** `projects:write`, `users:read`, `roles:read`

Weist einer E-Mail eine oder mehrere mandantenweite Rollen zu und vergibt optional Mitgliedschaften auf Projekten und/oder Projektregionen. Der API-Schlüssel muss ein reiner Kunden-Schlüssel sein.

**Bestehender Benutzer** (`status: ASSIGNED`): Die E-Mail gehört bereits zu einem Benutzer des Mandanten (Vergleich ohne Groß-/Kleinschreibung). Alle angegebenen Rollen werden mandantenweit hinzugefügt; bereits vorhandene Rollen bleiben bestehen. Jede Projektmitgliedschaft verwendet die **erste** Rolle als projektbezogene Rolle und ersetzt bei Wiederholung diese Rolle. Regionsmitgliedschaften werden angelegt; bestehende Regionszeilen bleiben unverändert. `projects` und `regions` dürfen entfallen.

**Unbekannte E-Mail** (`status: INVITED`): Es wird mindestens ein Projekt oder eine Region benötigt. Pro Projekt wird eine ausstehende Einladung mit der ersten Rolle gespeichert, pro Region eine Einladung ohne Rolle. Weitere Rollen werden geprüft und in `role_ids` zurückgegeben. Mandantenweit gespeichert werden sie, sobald die E-Mail zu einem Benutzer gehört. Wiederholen Sie die Anfrage danach, um alle mandantenweiten Rollen zu setzen.

**Adressierung:** Jeder Projekteintrag enthält genau eines von `project_number` oder `external_id`. `project_number` ist nur je Buchungskreis eindeutig; ist sie im Mandanten mehrfach vergeben, antwortet die API mit HTTP 409 — verwenden Sie dann `external_id`. Regionen werden über `region_number` adressiert.

**Upsert:** Eine Wiederholung aktualisiert die bestehenden Zeilen. Ausgelassene Projekte, Regionen und Rollen bleiben unverändert. Alle Schreibvorgänge einer Anfrage laufen in einer Mutation und werden gemeinsam übernommen oder gemeinsam verworfen.

Leerzeichen an `email`, Rollentiteln und Kennungen werden entfernt. Rollentitel müssen exakt einer bestehenden Rolle des Mandanten entsprechen.


## Overview

Assigns tenant-wide roles to an email and optionally grants project and region memberships. Repeating the request updates the existing rows. Assignments left out of the request stay as they are.

The API key must be a **customer API key**.

## Permissions

| Scope | Description |
| - | - |
| `projects:write` | Create and update projects |
| `users:read` | Read user data |
| `roles:read` | Read role data |

## Behavior

* Role titles must match an existing tenant role exactly. The **first** role is the project-scoped role on every membership and every project invite.
* When the email already belongs to a tenant user, every listed role is added tenant-wide (`ASSIGNED`). Roles, projects, and regions omitted from the request stay as they are. Sending the request again replaces the project-scoped role with the first role of the new request.
* When the email is unknown, `projects` or `regions` is required (`INVITED`). The project invite stores the first role; region invites carry no role. Further roles are validated and returned in `role_ids`. Send the request again after the user exists to apply every tenant-wide role.
* `project_number` is unique per legal entity. If more than one project in the tenant uses it, the API responds with **409**; use `external_id`.
* Each project entry contains exactly one of `project_number` or `external_id`. The same project or region must not appear twice, including when two identifiers resolve to the same target.

## Response codes

| Code | Description |
| - | - |
| `201` | Assignment or invites stored |
| `400` | Invalid request |
| `401` | Unauthorized |
| `403` | Missing permission or not a customer API key |
| `404` | Project, region, or role not found |
| `409` | `project_number` is ambiguous in the tenant |
| `500` | Assignment or invites could not be stored |


## OpenAPI

````yaml POST /projects/user-assignments
openapi: 3.0.3
info:
  title: comstruct Public API
  description: >
    Die comstruct API ist eine umfassende und flexible Lösung zur Optimierung
    des Materialbeschaffungsprozesses für Unternehmen. Diese API bietet eine
    einfache Schnittstelle für Entwickler, um auf Materialbeschaffungsdaten
    zuzugreifen und diese zu verwalten, einschließlich Lieferanteninformationen,
    Lieferungen und Projekte.


    ## Erste Schritte

    Um Zugang zur comstruct API zu erhalten, wenden Sie sich bitte an Ihren
    zuständigen Customer Success Manager. Unser Expertenteam steht Ihnen mit
    erstklassigem Support zur Verfügung, um Ihnen zu helfen, das Beste aus
    unserer API herauszuholen.


    ## Authentifizierung

    Alle API-Endpunkte unter `/v1` erfordern eine Authentifizierung mittels
    API-Schlüssel im `x-api-key`-Header. Jeder API-Schlüssel hat spezifische
    Berechtigungen (Scopes), die bestimmen, welche Endpunkte und Operationen
    verfügbar sind. Die Authentifizierung wird durch Middleware durchgesetzt,
    die den API-Schlüssel und die Berechtigungen für jede Anfrage validiert.


    Kalender-Endpunkte unter `/calendars` und IDS-Endpunkte unter `/ids` liegen
    **ohne** `/v1`-Präfix (Basis-URL `https://api.comstruct.com`). Kalender
    verwenden Token-basierte Authentifizierung; IDS ist ein öffentlicher
    Callback ohne API-Schlüssel.


    ## Datenformate

    - Alle Zeitstempel sind im ISO 8601-Format (UTC)

    - Geldbeträge werden als Dezimalzahlen dargestellt

    - IDs sind UUIDs, sofern nicht anders angegeben


    ## Anfragegrößenbeschränkungen

    - PDF-Rechnungsverarbeitung, benutzerdefinierte Rechnungsverarbeitung und
    Workflow-Verarbeitung: 32MiB

    - Asynchroner Lieferschein-PDF-Upload (`POST /deliveries/pdf`): 16MiB

    - Alle anderen Endpunkte: 10MiB


    ## Fehlerbehandlung

    Die API verwendet Standard-HTTP-Statuscodes und gibt detaillierte
    Fehlermeldungen im JSON-Format zurück. Weitere Details finden Sie in den
    Fehlerschemas.


    ## Integrationsmuster

    - **SAP-Integration**: Spezialisierte Endpunkte für SAP-ERP-Systeme

    - **Projektverwaltung**: Vollständiges Projektlebenszyklusmanagement mit
    Benutzerrollen

    - **Lieferverfolgung**: Unterstützung mehrerer Lieferscheinformate
    (OpenTrans, PAHM, Q-Point, benutzerdefiniert)

    - **Rechnungsverarbeitung**: Automatisierte Rechnungsanalyse und
    -validierung mit KI/GPT-Unterstützung

    - **Auftragsverwaltung**: IDS-Auftragsverarbeitung mit XML-Parsing und
    Projektkalenderintegration

    - **Kalenderintegration**: Separate Kalender-Endpunkte für
    iCalendar-Abonnement-Feeds
  version: 1.0.11
  license:
    name: Proprietary
    url: https://comstruct.com
  contact:
    name: comstruct ICT GmbH
    url: https://comstruct.com
    email: support@comstruct.com
  termsOfService: https://comstruct.com/datenschutzerklarung/
  x-logo:
    url: https://app.comstruct.com/logo-light-text.png
    altText: comstruct logo
servers:
  - url: https://api.comstruct.com/v1
    description: Haupt-API-Endpunkte (erfordert API-Schlüssel-Authentifizierung)
    variables: {}
  - url: https://api.comstruct.com
    description: Basisserver für Kalender- und IDS-Endpunkte (andere Authentifizierung)
    variables: {}
security:
  - ApiKey: []
tags:
  - name: Projects
    description: Endpunkte für Projekte.
  - name: Projects (SAP)
    description: SAP-spezifische Projekt-Endpunkte.
  - name: Project Regions
    description: Endpunkte für die Verwaltung von Projektregionen.
  - name: Deliveries
    description: Endpunkte für Lieferungen.
  - name: Deliveries (Supplier)
    description: Lieferantenspezifische Liefer-Endpunkte.
  - name: Accounts
    description: Endpunkte für die Verwaltung von Sachkonten.
  - name: Payment Terms
    description: Endpunkte für die Verwaltung von Zahlungsbedingungen.
  - name: Tax Codes
    description: Endpunkte für die Verwaltung von Steuercodes.
  - name: Company Codes
    description: Endpunkte für die Verwaltung von Buchungskreisen (juristische Einheiten).
  - name: Suppliers
    description: Endpunkte für die Verwaltung von Lieferanten.
  - name: Purchase Orders
    description: Endpunkte für Bestellungen.
  - name: Purchase Orders (SAP)
    description: SAP-spezifische Bestellungs-Endpunkte.
  - name: Orders (Supplier)
    description: >-
      Lieferantenspezifische Bestellungs-Endpunkte (Bestätigung, Ablehnung,
      Bearbeitung).
  - name: Suppliers (SAP)
    description: SAP-spezifische Lieferanten-Endpunkte.
  - name: Invoices
    description: Endpunkte für Rechnungen.
  - name: Invoices (Supplier)
    description: Lieferantenspezifische Rechnungs-Endpunkte.
  - name: Invoices (SAP)
    description: SAP-spezifische Rechnungs-Endpunkte.
  - name: Invoice Dimensions
    description: >
      Rechnungs-Dimensionen (benutzerdefinierte Eigenschaften) und Zuweisungen
      auf Rechnung (`header`), Position (`line_item`) oder Kontierung
      (`account`).


      Dimensionen haben den Typ `option` (vordefinierte Werte) oder `text`
      (Freitext über `dimension_id` + `text_value`). Bulk-Konto-POST
      (`/assignments/account/bulk`) unterstützt nur Options-Zuweisungen über
      `option_ids`; Freitext auf Kontoebene über Einzel-POST, PATCH-Bulk oder
      Positions-Bulk.
  - name: Workflows
    description: Endpunkte für Workflow- und Prozessmanagement.
  - name: Calendar
    description: Kalender-Abonnement-Endpunkte mit separater Authentifizierung.
  - name: Orders
    description: Endpunkte für Auftragsverarbeitung und -verwaltung.
paths:
  /projects/user-assignments:
    post:
      tags:
        - Projects
      summary: Benutzerrollen und Mitgliedschaften zuweisen
      description: >
        **Erforderliche Berechtigungen:** `projects:write`, `users:read`,
        `roles:read`


        Weist einer E-Mail eine oder mehrere mandantenweite Rollen zu und
        vergibt optional Mitgliedschaften auf Projekten und/oder
        Projektregionen. Der API-Schlüssel muss ein reiner Kunden-Schlüssel
        sein.


        **Bestehender Benutzer** (`status: ASSIGNED`): Die E-Mail gehört bereits
        zu einem Benutzer des Mandanten (Vergleich ohne Groß-/Kleinschreibung).
        Alle angegebenen Rollen werden mandantenweit hinzugefügt; bereits
        vorhandene Rollen bleiben bestehen. Jede Projektmitgliedschaft verwendet
        die **erste** Rolle als projektbezogene Rolle und ersetzt bei
        Wiederholung diese Rolle. Regionsmitgliedschaften werden angelegt;
        bestehende Regionszeilen bleiben unverändert. `projects` und `regions`
        dürfen entfallen.


        **Unbekannte E-Mail** (`status: INVITED`): Es wird mindestens ein
        Projekt oder eine Region benötigt. Pro Projekt wird eine ausstehende
        Einladung mit der ersten Rolle gespeichert, pro Region eine Einladung
        ohne Rolle. Weitere Rollen werden geprüft und in `role_ids`
        zurückgegeben. Mandantenweit gespeichert werden sie, sobald die E-Mail
        zu einem Benutzer gehört. Wiederholen Sie die Anfrage danach, um alle
        mandantenweiten Rollen zu setzen.


        **Adressierung:** Jeder Projekteintrag enthält genau eines von
        `project_number` oder `external_id`. `project_number` ist nur je
        Buchungskreis eindeutig; ist sie im Mandanten mehrfach vergeben,
        antwortet die API mit HTTP 409 — verwenden Sie dann `external_id`.
        Regionen werden über `region_number` adressiert.


        **Upsert:** Eine Wiederholung aktualisiert die bestehenden Zeilen.
        Ausgelassene Projekte, Regionen und Rollen bleiben unverändert. Alle
        Schreibvorgänge einer Anfrage laufen in einer Mutation und werden
        gemeinsam übernommen oder gemeinsam verworfen.


        Leerzeichen an `email`, Rollentiteln und Kennungen werden entfernt.
        Rollentitel müssen exakt einer bestehenden Rolle des Mandanten
        entsprechen.
      operationId: assignProjectUser
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AssignProjectUserRequest'
            examples:
              project_by_number:
                summary: Bestehenden Benutzer einem Projekt zuweisen
                value:
                  email: jane.doe@example.com
                  roles:
                    - MANAGER
                  projects:
                    - project_number: PRJ-0001
              project_and_region:
                summary: Mehrere Rollen, Projekt über external_id und Region
                value:
                  email: jane.doe@example.com
                  roles:
                    - MANAGER
                    - CONTROLLER
                  projects:
                    - external_id: ERP-4711
                  regions:
                    - region_number: REG-001
              roles_only:
                summary: Nur mandantenweite Rollen
                value:
                  email: jane.doe@example.com
                  roles:
                    - MANAGER
      responses:
        '201':
          description: Zuweisung oder Einladungen gespeichert
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AssignProjectUserResponse'
              examples:
                assigned:
                  summary: Benutzer existiert bereits
                  value:
                    success: true
                    status: ASSIGNED
                    email: jane.doe@example.com
                    role_ids:
                      - 44444444-4444-4444-8444-444444444444
                    project_ids:
                      - 33333333-3333-4333-8333-333333333333
                    region_ids: []
                invited:
                  summary: E-Mail ist noch kein Benutzer
                  value:
                    success: true
                    status: INVITED
                    email: jane.doe@example.com
                    role_ids:
                      - 44444444-4444-4444-8444-444444444444
                    project_ids:
                      - 33333333-3333-4333-8333-333333333333
                    region_ids:
                      - 55555555-5555-4555-8555-555555555555
        '400':
          description: >
            Ungültige E-Mail, leere oder doppelte Rollen, doppelte Projekte oder
            Regionen,

            ein Eintrag mit beiden oder ohne `project_number` und `external_id`,
            oder

            `projects` und `regions` fehlen für eine E-Mail, die keinem Benutzer
            gehört.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                message: Provide exactly one of project_number or external_id
                statusCode: 400
                success: false
        '401':
          description: Nicht autorisiert — fehlender oder ungültiger API-Schlüssel
        '403':
          description: >-
            Verboten — fehlende Berechtigung oder kein reiner
            Kunden-API-Schlüssel
        '404':
          description: Projekt, Region oder Rolle existiert im Mandanten nicht
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                message: 'Role(s) not found: MANAGER'
                statusCode: 404
                success: false
        '409':
          description: >
            Die `project_number` wird von mehr als einem Buchungskreis des
            Mandanten verwendet

            und ist daher mehrdeutig. Adressieren Sie das Projekt über
            `external_id`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                message: >-
                  project_number PRJ-0001 is used by 2 projects of this tenant,
                  use external_id instead
                statusCode: 409
                success: false
        '500':
          description: Die Zuweisung oder die Einladungen konnten nicht gespeichert werden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - ApiKey:
            - projects:write
            - users:read
            - roles:read
components:
  schemas:
    AssignProjectUserRequest:
      type: object
      required:
        - email
        - roles
      properties:
        email:
          type: string
          format: email
          description: >-
            E-Mail-Adresse, der die Rollen und Mitgliedschaften zugewiesen
            werden.
          example: jane.doe@example.com
        roles:
          type: array
          minItems: 1
          uniqueItems: true
          description: >
            Titel der mandantenweiten Rollen. Mindestens eine, ohne Duplikate.

            Jede Rolle muss im Mandanten existieren. Bei Projekten wird die
            erste Rolle

            als projektbezogene Rolle verwendet.
          items:
            type: string
          example:
            - MANAGER
            - CONTROLLER
        projects:
          type: array
          description: >
            Optionale Projekte. Jeder Eintrag enthält genau eines von
            `project_number` oder `external_id`.

            Dasselbe Projekt darf nicht zweimal vorkommen. Für unbekannte
            E-Mails ist mindestens

            ein Projekt oder eine Region erforderlich.
          items:
            $ref: '#/components/schemas/AssignProjectIdentifier'
        regions:
          type: array
          description: >
            Optionale Projektregionen, adressiert über `region_number`.
            Duplikate werden abgelehnt.

            Bestehende Benutzer erhalten die Mitgliedschaft sofort; unbekannte
            E-Mails eine ausstehende Einladung.
          items:
            $ref: '#/components/schemas/AssignRegionIdentifier'
    AssignProjectUserResponse:
      type: object
      required:
        - success
        - status
        - email
        - role_ids
        - project_ids
        - region_ids
      properties:
        success:
          type: boolean
          description: Ob die Zuweisung gespeichert wurde
          example: true
        status:
          type: string
          enum:
            - ASSIGNED
            - INVITED
          description: >
            `ASSIGNED`, wenn die E-Mail bereits zu einem Benutzer des Mandanten
            gehört.

            `INVITED`, wenn stattdessen ausstehende Projekt- und/oder
            Regionseinladungen gespeichert wurden.
          example: ASSIGNED
        email:
          type: string
          format: email
          description: E-Mail, für die die Zuweisung gespeichert wurde
          example: jane.doe@example.com
        role_ids:
          type: array
          description: >-
            UUIDs der aufgelösten mandantenweiten Rollen, in der Reihenfolge der
            Anfrage
          items:
            type: string
            format: uuid
          example:
            - 44444444-4444-4444-8444-444444444444
        project_ids:
          type: array
          description: >-
            UUIDs der aufgelösten Projekte. Leer, wenn nur Rollen und/oder
            Regionen zugewiesen wurden.
          items:
            type: string
            format: uuid
          example:
            - 33333333-3333-4333-8333-333333333333
        region_ids:
          type: array
          description: >-
            UUIDs der aufgelösten Projektregionen. Leer, wenn keine Regionen
            angefragt wurden.
          items:
            type: string
            format: uuid
          example:
            - 55555555-5555-4555-8555-555555555555
    ErrorResponse:
      type: object
      properties:
        error:
          type: string
          description: Fehlermeldung, die beschreibt, was schiefgelaufen ist
        message:
          type: string
          description: Zusätzliche Fehlerdetails oder benutzerfreundliche Nachricht
        success:
          type: boolean
          description: Zeigt Fehlschlag an, wenn in Fehlerantworten vorhanden
      anyOf:
        - required:
            - error
        - required:
            - message
        - required:
            - success
      example:
        error: Validation failed
        message: The provided data did not pass validation checks
    AssignProjectIdentifier:
      type: object
      description: Adressiert genau ein Projekt über `project_number` oder `external_id`.
      properties:
        project_number:
          type: string
          description: >
            Projektnummer, eindeutig je Buchungskreis. Schließt `external_id`
            aus.

            Ist die Nummer im Mandanten mehrfach vergeben, antwortet die API mit
            HTTP 409.
          example: PRJ-0001
        external_id:
          type: string
          description: >-
            Externe Projekt-ID des Quellsystems, eindeutig je Mandant. Schließt
            `project_number` aus.
          example: ERP-4711
    AssignRegionIdentifier:
      type: object
      required:
        - region_number
      properties:
        region_number:
          type: string
          description: Projektregionsnummer, eindeutig je Mandant.
          example: REG-001
  securitySchemes:
    ApiKey:
      type: apiKey
      in: header
      name: X-API-Key
      description: >
        API-Schlüssel zur Authentifizierung. Kontaktieren Sie Ihren Customer
        Success Manager, um einen API-Schlüssel zu erhalten.


        Jeder Endpunkt erfordert spezifische Berechtigungen (Scopes); die
        erforderlichen Scopes werden pro Endpunkt angezeigt.

````

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