openapi: 3.0.1
info:
  title: API
  description: |
    This API enables secure integration between third‑party systems and the
    GemeindeConnect.ch Form Designer. Its main purpose is that providers of 
    government solutions at a communal and state level can retrieve and update
    the data and submit updates, such as changes in thwe status, back to 
    GemeindeConnect.ch.
    
    It allows external applications to list and search for submitted forms as 
    well as to submit form data.
    
    Authentication is performed by exchanging a published API key for a
    short‑lived Bearer (JWT) token. The published API Key is per tenant (municipality)
    and can be retrieved from the Cockpit of the form designer together with the
    tenantId.
  version: v1
servers:
- url: https://api.gemeindeconnect.ch/core
  description: Production 
- url: https://api-test.gemeindeconnect.ch/core
  description: Test API
tags:
- name: Auth
  description: 'Authentication endpoints: exchange API key for a Bearer JWT.'
- name: Form
  description: 'Manage individual form instances: retrieve documents, submit form data, update document status, and search or count submitted forms.'
- name: Tenant
  description: 'Tenant management endpoints: retrieve tenant details'
security:
- BearerAuth: []
paths:
  /auth/token:
    get:
      operationId: exchangeApiKeyForToken
      tags:
      - Auth
      summary: Exchange API key for Bearer token
      description: | 
        Accepts an API key and returns a Bearer JWT token.
        The API key can be retrieved from the Cockpit. There is one API Key per Tenant.
      security: []
      parameters:
        - name: x-api-key
          in: header
          required: true
          schema:
            type: string
          description: API key to exchange for a Bearer token. The API key can be retrieved from the Cockpit.
        - name: tenantId
          in: query
          schema:
            type: integer
            format: int32
          required: true
          description: Required to identify the tenant. The tenantId can be retrieved from the Cockpit.
      responses:
        "200":
          description: OK
          content:
            text/plain:
              schema:
                type: string
                description: JWT bearer token
              example: "eyJhbGciOiJ... (jwt)"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema: { $ref: '#/components/schemas/ErrorResponse' }
              example:
                code: "Unauthorized"
                message: "Missing or invalid Bearer token."
        "500":
          description: Internal server error
          content:
            application/json:
              schema: { $ref: '#/components/schemas/ErrorResponse' }
              example:
                code: "ServerError"
                message: "Unexpected error. Please retry later."
  /Form/count:
    get:
      tags:
      - Form
      operationId: getFormCounts
      summary: Get form instance counts by form design and status
      description: |-
        Retrieve a summary of submitted form instances grouped by form design and status.
        
        The return result can be used to determine how many form instances are with which status and which form design.
        An example use can be to display an overview for a user.
      parameters:
      - name: tenantId
        in: query
        schema:
          type: integer
          format: int32
        description: Required to identify the tenant. The tenantId can be retrieved from the Cockpit.
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Cpro.Forms.Service.Models.FormNavigation'
              examples:
                multiStatusFormNavigations:
                  summary: One form design with three status
                  value:
                    - id: "16171dbd-a37f-4628-adfa-bc4e4ba9de81"
                      name: "Projektbeitragsgesuch"
                      count: 5
                      request:
                        formId: "16171dbd-a37f-4628-adfa-bc4e4ba9de81"
                        formStateConfigId: 0
                        page: 0
                        pageSize: 50
                      formNavigations:
                        - id: "16171dbd-a37f-4628-adfa-bc4e4ba9de81-Neu"
                          name: "Neu"
                          count: 2
                          request:
                            formId: "16171dbd-a37f-4628-adfa-bc4e4ba9de81"
                            status: "Neu"
                            formStateConfigId: 35
                            page: 0
                            pageSize: 50
                        - id: "16171dbd-a37f-4628-adfa-bc4e4ba9de81-InBearbeitung"
                          name: "In Bearbeitung"
                          count: 1
                          request:
                            formId: "16171dbd-a37f-4628-adfa-bc4e4ba9de81"
                            status: "In Bearbeitung"
                            formStateConfigId: 36
                            page: 0
                            pageSize: 50
                        - id: "16171dbd-a37f-4628-adfa-bc4e4ba9de81-Abgeschlossen"
                          name: "Abgeschlossen"
                          count: 2
                          request:
                            formId: "16171dbd-a37f-4628-adfa-bc4e4ba9de81"
                            status: "Abgeschlossen"
                            formStateConfigId: 37
                            page: 0
                            pageSize: 50
                emptyFormNavigations:
                  summary: No submitted forms for a form design
                  value:
                    - id: "02b189c7-ee66-4620-8851-fdcf64be43be"
                      name: "Wohnsitzbescheinigung"
                      count: 0
                      request:
                        formId: "02b189c7-ee66-4620-8851-fdcf64be43be"
                        formStateConfigId: 0
                        page: 0
                        pageSize: 50
                      formNavigations: []
        "401":
          description: Unauthorized
          content:
            application/json:
              schema: { $ref: '#/components/schemas/ErrorResponse' }
              example:
                code: "Unauthorized"
                message: "Missing or invalid Bearer token."

        "500":
          description: Internal server error
          content:
            application/json:
              schema: { $ref: '#/components/schemas/ErrorResponse' }
              example:
                code: "ServerError"
                message: "Unexpected error. Please retry later."
  /Form/search:
    post:
      tags:
      - Form
      operationId: searchForms
      summary: Search submitted forms
      description: Search forms using the supplied criteria. Returns paged results of form data.
      parameters:
      - name: tenantId
        in: query
        schema:
          type: integer
          format: int32
        required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Cpro.Forms.Service.Models.FormSearchRequest'
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PagingResponse_FormData'
              example:
                data:
                  - id: "a4c70dfd-1bc0-4a73-847d-4b620b50ca9a"
                    name: "Bestätigung der Kindesanerkennung bestellen "
                    documentId: "1934912"
                    status: "Neu"
                    tenantId: 15
                    formId: "2cf5e9a5-bb0b-41e1-bf71-9b75cb72897f"
                    tenantName: "Stadt Zürich"
                    submittedDate: "2025-09-02T13:42:02.7078251"
                totalCount: 1
                pageNumber: 1
                pageSize: 100
        "401":
          description: Unauthorized
          content:
            application/json:
              schema: { $ref: '#/components/schemas/ErrorResponse' }
              example:
                code: "Unauthorized"
                message: "Missing or invalid Bearer token."

        "500":
          description: Internal server error
          content:
            application/json:
              schema: { $ref: '#/components/schemas/ErrorResponse' }
              example:
                code: "ServerError"
                message: "Unexpected error. Please retry later."
  /Form/{formId}/data/{documentId}:
    get:
      tags:
      - Form
      operationId: getFormDocument
      summary: Get form details by documentId
      description: Retrieve a specific document by documentId for the given form. Returns the document response payload.
      parameters:
      - name: formId
        in: path
        required: true
        description: Form design GUID. Can be retrieved from the /Form/count or Form/search endpoint.
        schema:
          type: string
          format: uuid
      - name: tenantId
        in: query
        schema:
          type: integer
          format: int32
        required: true
        description: Required to identify the tenant. The tenantId can be retrieved from the Cockpit.
      - name: documentId
        in: path
        required: true
        schema:
          type: string
        description: Document ID Can be retrieved from the /Form/search endpoint and identifies a submitted form instance.
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Cpro.Forms.Service.Models.DocumentDataResponse'
        "401":
          description: Unauthorized
          content:
            application/json:
              schema: { $ref: '#/components/schemas/ErrorResponse' }
              example:
                code: "Unauthorized"
                message: "Missing or invalid Bearer token."

        "500":
          description: Internal server error
          content:
            application/json:
              schema: { $ref: '#/components/schemas/ErrorResponse' }
              example:
                code: "ServerError"
                message: "Unexpected error. Please retry later."
    patch:
      tags:
      - Form
      operationId: patchFormDocument
      summary: Update form instance field values by documentId
      description: Update form field values. Only submit fields that need to be updated. Important that the name of the field
        matches the name in the form design as retrieved in the get /Form/{formId}/document/{documentId} endpoint.
      parameters:
      - name: formId
        in: path
        required: true
        description: Form design GUID. Can be retrieved from the /Form/count or Form/search endpoint.
        schema:
          type: string
          format: uuid
      - name: tenantId
        in: query
        schema:
          type: integer
          format: int32
        required: true
        description: Required to identify the tenant. The tenantId can be retrieved from the Cockpit.
      - name: documentId
        in: path
        required: true
        schema:
          type: string
        description: Document ID Can be retrieved from the /Form/search endpoint and identifies a submitted form instance.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Cpro.Forms.Service.Models.UpdateFormRequest'
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Cpro.Forms.Service.Models.DocumentDataResponse'
        "401":
          description: Unauthorized
          content:
            application/json:
              schema: { $ref: '#/components/schemas/ErrorResponse' }
              example:
                code: "Unauthorized"
                message: "Missing or invalid Bearer token."

        "500":
          description: Internal server error
          content:
            application/json:
              schema: { $ref: '#/components/schemas/ErrorResponse' }
              example:
                code: "ServerError"
                message: "Unexpected error. Please retry later."
  /Form/{formId}/data/{documentId}/upload:
    patch:
      tags:
        - Form
      operationId: uploadFileToFormDocument
      summary: Upload a file to a file upload field in a form instance
      description: Upload a file to a file upload field in a form instance. The file will be added to the specified tab and field name.
      parameters:
        - name: formId
          in: path
          required: true
          schema:
            type: string
        - name: tenantId
          in: query
          schema:
            type: integer
            format: int32
        - name: documentId
          in: path
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Cpro.Forms.Service.Models.DocumentUploadRequest'
      responses:
        '200':
          description: OK
  /Tenant/{id}:
    get:
      tags:
      - Tenant
      operationId: getTenantById
      summary: Get tenant details by id
      description: Retrieve tenant details by id. The tenantId can be retrieved from the Cockpit.
      parameters:
      - name: id
        in: path
        required: true
        description: Tenant ID (municipality) to retrieve details for. Can be retrieved from the Cockpit.
        schema:
          type: integer
          format: int32
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Cpro.Forms.Service.Models.TenantResponse'
              example:
                id: "65727e7e-4a86-43b9-acc9-4292d87aa87b"
                tenantId: 15
                tenantName: "Stadt Zürich"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema: { $ref: '#/components/schemas/ErrorResponse' }
              example:
                code: "Unauthorized"
                message: "Missing or invalid Bearer token."

        "500":
          description: Internal server error
          content:
            application/json:
              schema: { $ref: '#/components/schemas/ErrorResponse' }
              example:
                code: "ServerError"
                message: "Unexpected error. Please retry later."
components:
  schemas:
    ErrorResponse:
      type: object
      properties:
        traceId:
          type: string
          description: Correlation identifier for troubleshooting.
        code:
          type: string
          description: Machine-readable error code.
        message:
          type: string
          description: Human-readable error message.
      required: [message]
    Cpro.Forms.Service.Models.DocumentResponse:
      type: object
      properties:
        documentTypeName:
          type: string
          nullable: true
          description: Name of the form design the document is based on.
        name:
          type: string
          nullable: true
          description: Human readable name of the form instance. Currently the same as documentTypeName
        formStatesConfig:
          type: array
          items:
            $ref: '#/components/schemas/Cpro.Forms.Service.Models.FormStatesConfig'
          nullable: true
          description: Possible future states for the form instance. Those states can be used in the put request to update the status.
        fields:
          type: array
          items:
            $ref: '#/components/schemas/Cpro.Forms.Service.Models.IndexField'
          nullable: true
          description: Array of fields with their data in the form instance.
        state:
          type: string
          nullable: true
          description: Current status of the form instance.
        tags:
          type: array
          items:
            type: string
          nullable: true
          description: Array of tags assigned to the form instance. Tags can be used in the keyword property when searching for forms.
      additionalProperties: false
    Cpro.Forms.Service.Models.FileUploadAdditionalData:
      type: object
      properties:
        key:
          type: string
          nullable: true
        base64File:
          type: string
          nullable: true
        name:
          type: string
          nullable: true
        type:
          type: string
          nullable: true
      additionalProperties: false
    Cpro.Forms.Service.Models.FormData:
      type: object
      properties:
        id:
          type: string
          format: uuid
          nullable: true
          description: Document GUID.
        name:
          type: string
          nullable: true
          description: Human readable name of the form instance.
        documentId:
          type: string
          nullable: true
          description: Document ID (which can be used in the /Form/{formId}/document/{documentId} endpoint)
            to get the details of this form instance.
        status:
          type: string
          nullable: true
          description: Current status of the form instance.
        tenantId:
          type: integer
          format: int32
          description: Tenant ID (municipality) the form instance belongs to.
        formId:
          type: string
          nullable: true
          format: uuid
          description: Form design GUID the form instance is based on.
        tenantName:
          type: string
          nullable: true
          description: Human readable name of the tenant (municipality). E.g. "Stadt Zürich".
        submittedDate:
          type: string
          format: date-time
          description: Date and time when the form instance was submitted.
      additionalProperties: false
    Cpro.Forms.Service.Models.FormNavigation:
      type: object
      description: >-
        Summary for a form design: total counts for the form and an optional
        per‑status breakdown. Each FormNavigation object points to a reusable
        request you can use to fetch the actual instances.
      properties:
        id:
          type: string
          nullable: true
          description: "Form design GUID (same as formId)."
        name:
          type: string
          nullable: true
          description: "Human readable name of the form (e.g. 'Hauptwohnsitzbescheinigung')."
        count:
          type: integer
          format: int32
          description: "Total number of submitted form instances (across all statuses)."
        request:
          $ref: '#/components/schemas/Cpro.Forms.Service.Models.Request'
          description: >-
            Reusable request payload to fetch instances for this form. Typical
            fields: formId, formStateConfigId, page, pageSize and optional status.
        formNavigations:
          type: array
          items:
            $ref: '#/components/schemas/Cpro.Forms.Service.Models.FormStatusNavigation'
          nullable: true
          description: >-
            Per-status breakdown. Empty array means no submitted documents
            exist for this form/status. When populated, there is one entry per status.
      additionalProperties: false
    Cpro.Forms.Service.Models.FormSearchRequest:
      type: object
      properties:
        keyword:
          type: string
          nullable: true
          description: Keyword to search in submitted forms. It can be a full or partial match of a
            Form Name or a Tag of a form.
        formId:
          type: string
          nullable: true
          description: a formId to filter the search results. The formId is the GUID returned in the 
            /Form/count endpoint as "id".
        status:
          type: string
          nullable: true
          description: Status to filter the search results. E.g. "Neu", "In Bearbeitung", "Abgeschlossen".
        page:
          type: integer
          format: int32
          default: 0
          description: Page number. If not provided, defaults to 0.
        pageSize:
          type: integer
          format: int32
          default: 50
          description: Number of items per page. If not provided, defaults to 50.
        orderBy:
          type: string
          nullable: true
          description: Field to order the results by. E.g. "submittedDate", "name".
        orderByDirection:
          $ref: '#/components/schemas/Peritos.Common.Abstractions.Paging.PagingParametersOrderByDirectionEnum'
      additionalProperties: false
    Cpro.Forms.Service.Models.FormStatusNavigation:
      type: object
      description: "Per-status entry for a form design; provides count and a request to fetch instances for that status."
      properties:
        id:
          type: string
          nullable: true
          description: "The form design Id"
        name:
          type: string
          nullable: true
          description: "Status name (e.g. 'Neu', 'In Bearbeitung', 'Abgeschlossen')."
        count:
          type: integer
          format: int32
          description: "Number of submitted instances of this form that currently have this status."
        request:
          $ref: '#/components/schemas/Cpro.Forms.Service.Models.Request'
          description: >-
            Reusable payload to fetch instances in this status. Includes status,
            formStateConfigId, page, pageSize (and formId).
      additionalProperties: false
    Cpro.Forms.Service.Models.IndexField:
      type: object
      properties:
        id:
          type: integer
          format: int32
          nullable: true
          description: Unique identifier of the field within the form instance.
        sortOrder:
          type: integer
          format: int32
          description: Order of the field within the form instance. This is the order the fields are visible to the user submitting the form and the processor
            viewing the submitted form in the Cockpit.
        name:
          type: string
          nullable: true
          description: Internal name of the field within the form design. This id can be used to update the field value to update the data in the form instance.
        displayName:
          type: string
          nullable: true
          description: The label of the field as it is displayed to the user submitting the form and in the Cockpit.
        datatype:
          type: string
          nullable: true
          description: Data type of the field from the form designer.
        value:
          type: string
          nullable: true
          description: The value submitted for this field in the form instance.
        description:
          type: string
          nullable: true
          description: Description or help text for the field as defined in the form designer and displayed to the user when submitting the form.
        fileUploadAdditionalData:
          type: array
          items:
            $ref: '#/components/schemas/Cpro.Forms.Service.Models.FileUploadAdditionalData'
          nullable: true
          description: Fileattachments uploaded by the user in a file upload field.
        lookupValues:
          type: array
          items:
            $ref: '#/components/schemas/Cpro.Forms.Service.Models.LookupValues'
          nullable: true
          description: Possible lookup values for fields of datatype lookup, radio, dropdown, checkboxgroup.
        tabName:
          type: string
          nullable: true
          description: Name of the tab the field is located in within the form design.
      additionalProperties: false
    Cpro.Forms.Service.Models.LookupValues:
      type: object
      properties:
        displayOrder:
          type: integer
          format: int32
        displayValue:
          type: string
          nullable: true
        value:
          type: string
          nullable: true
      additionalProperties: false
    Cpro.Forms.Service.Models.Request:
      type: object
      properties:
        keyword:
          type: string
          nullable: true
        formId:
          type: string
          nullable: true
        status:
          type: string
          nullable: true
        formStateConfigId:
          type: integer
          format: int32
          description: >-
            An id per form State, unique within the system. Identifies the Status for this particular form.
        page:
          type: integer
          format: int32
        pageSize:
          type: integer
          format: int32
        orderBy:
          type: string
          nullable: true
        orderByDirection:
          type: string
          nullable: true
      additionalProperties: false
    Peritos.Common.Abstractions.Paging.PagingParametersOrderByDirectionEnum:
      enum:
      - Ascending
      - Descending
      type: string
    PagingResponse_FormData:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Cpro.Forms.Service.Models.FormData'
          nullable: true
        totalCount:
          type: integer
          format: int32
          description: Total number of submitted forms available.
        pageNumber:
          type: integer
          format: int32
          description: Current page number.
        pageSize:
          type: integer
          format: int32
          description: Number of forms per page.
      additionalProperties: false
    Cpro.Forms.Service.Models.FormStatesConfig:
      type: object
      properties:
        formStatesConfigId:
          type: integer
          format: int32
          description: Unique identifier for the form state configuration. This Id is unique across all form designs. 
            It can be used to filter form instances by status.
        label:
          type: string
          nullable: true
          description: Human readable label of the form state (status). E.g. "Neu", "In Bearbeitung", "Abgeschlossen".
        value:
          type: string
          nullable: true
          description: Internal value of the form state (status). E.g. "Neu", "In Bearbeitung", "Abgeschlossen".
      additionalProperties: false
    Cpro.Forms.Service.Models.TenantResponse:
      type: object
      description: Represents tenant details as retrieved from the Digitale-Gemeinde Cockpit.
      properties:
        id:
          type: string
          format: uuid
          description: Unique identifier (GUID) of the tenant record.
        tenantId:
          type: integer
          format: int32
          description: Numeric tenant ID (municipality ID). This is the tenant identifier used in the Cockpit.
        tenantName:
          type: string
          description: Human-readable name of the tenant. For example, the name of the municipality (Stadt Zürich).
      required:
        - id
        - tenantId
        - tenantName
    Cpro.Forms.Service.Models.UpdateFormRequest:
      type: object
      description: Request payload to update form instance field values.
      properties:
        state:
          type: string
          nullable: true
          description: Optional new state (status) to set for the form instance. If provided, the form instance status will be updated.
          example: "In Bearbeitung"
        fields:
          type: array
          description: >
            Array of fields to update in the form instance. Only include fields that
            need to be updated. Each item must contain the field name and the value.
          minItems: 1
          items:
            type: object
            additionalProperties: false
            required:
              - tabName
              - name
              - value
            properties:
              tabName:
                type: string
                description: Name of the tab the field is located in within the form design.
                example: "Section 1"
              name:
                type: string
                description: Name of the field to update. Must match the field name in the form design.
                example: "FirstName-6e8cda36-ff0c-4b29-8689-6e1d22e63ea6"
              value:
                type: string
                nullable: true
                description: New value to set for the field (serialized as string; use ISO 8601 for dates).
                example: "John"
      required:
        - fields
      additionalProperties: false
    Cpro.Forms.Service.Models.DocumentDataResponse:
      type: object
      properties:
        fields:
          type: array
          items:
            $ref: '#/components/schemas/Cpro.Forms.Service.Models.IndexFieldData'
          nullable: true
        state:
          type: string
          nullable: true
      additionalProperties: false
    Cpro.Forms.Service.Models.IndexFieldData:
      type: object
      properties:
        tabName:
          type: string
          nullable: true
        name:
          type: string
          nullable: true
        value:
          type: string
          nullable: true
      additionalProperties: false
    Cpro.Forms.Service.Models.DocumentUploadRequest:
      type: object
      properties:
        tabname:
          type: string
          nullable: true
        name:
          type: string
          nullable: true
        fileContent:
          type: string
          nullable: true
      additionalProperties: false
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        Use the Authorization header with a Bearer JWT:
        Authorization: Bearer <token>
  

