{
  "openapi": "3.1.0",
  "info": {
    "title": "Getmomo Public API",
    "version": "1.4.0",
    "description": "Public API for interfacing with the Getmomo service offering.\n\nThis API supports both request/response endpoints and webhook event delivery. See the **Webhooks** section for details on event types, payload schemas, and signature verification.",
    "license": {
      "name": "Proprietary",
      "url": "https://getmomo.de/agb-uebersicht/"
    }
  },
  "servers": [
    {
      "url": "https://api.getmomo.app/public/v1",
      "description": "Production server"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/deposit-account": {
      "get": {
        "summary": "List all deposit accounts",
        "description": "Retrieves all deposit accounts with pagination support",
        "operationId": "listDepositAccounts",
        "tags": ["Deposit Accounts"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Number of items to skip before returning results",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            },
            "example": 15
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 15
            },
            "example": 15
          }
        ],
        "responses": {
          "200": {
            "description": "List of deposit accounts retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DepositAccountListResponse"
                },
                "example": {
                  "offset": 0,
                  "limit": 15,
                  "totalItems": 2,
                  "items": [
                    {
                      "id": "vWRaPWn3iIDr8iBpdAHpW",
                      "createdAt": "2025-09-15T09:00:00+02:00",
                      "updatedAt": "2025-10-20T11:30:00+02:00",
                      "name": "Property Management GmbH",
                      "title": "Primary Account",
                      "iban": "DE89370400440532013000",
                      "bic": "HSHNDEHHXXX",
                      "isDefault": true
                    },
                    {
                      "id": "moTEwlVvx2N7U7Eo9Kl6n",
                      "createdAt": "2025-09-20T14:15:00+02:00",
                      "updatedAt": "2025-10-22T16:45:00+02:00",
                      "name": "Property Management GmbH",
                      "iban": "DE89370400440532013001",
                      "bic": "HSHNDEHHXXX",
                      "isDefault": false
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/deposit-account/{depositAccountId}": {
      "get": {
        "summary": "Get a single deposit account",
        "description": "Retrieves a single deposit account by its unique identifier",
        "operationId": "getDepositAccount",
        "tags": ["Deposit Accounts"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "depositAccountId",
            "in": "path",
            "required": true,
            "description": "The unique identifier of the deposit account",
            "schema": {
              "type": "string"
            },
            "example": "q3a2bQPpNz2tu4nkTrjmI"
          }
        ],
        "responses": {
          "200": {
            "description": "Deposit account retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DepositAccount"
                },
                "example": {
                  "id": "q3a2bQPpNz2tu4nkTrjmI",
                  "createdAt": "2025-09-10T08:30:00+02:00",
                  "updatedAt": "2025-10-23T09:15:00+02:00",
                  "name": "Property Management GmbH",
                  "title": "Primary Account",
                  "iban": "DE89370400440532013000",
                  "bic": "HSHNDEHHXXX",
                  "isDefault": true
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/deposit-account/{depositAccountId}/virtual": {
      "get": {
        "summary": "List all virtual deposit accounts for a deposit account",
        "description": "Retrieves all virtual deposit accounts associated with a specific deposit account with pagination support",
        "operationId": "listVirtualDepositAccounts",
        "tags": ["Virtual Deposit Accounts"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "depositAccountId",
            "in": "path",
            "required": true,
            "description": "The unique identifier of the deposit account",
            "schema": {
              "type": "string"
            },
            "example": "TgQBfyro4OHY6Iza0zPQa"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Number of items to skip before returning results",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            },
            "example": 15
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 15
            },
            "example": 15
          }
        ],
        "responses": {
          "200": {
            "description": "List of virtual deposit accounts retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VirtualDepositAccountListResponse"
                },
                "example": {
                  "offset": 0,
                  "limit": 15,
                  "totalItems": 2,
                  "items": [
                    {
                      "id": "C9NS3gndTEXrX6CoHIyGy",
                      "createdAt": "2025-09-25T10:30:00+02:00",
                      "updatedAt": "2025-10-15T14:20:00+02:00",
                      "iban": "DE89370400440532013000",
                      "appLink": "https://getmomo.app/kautionsverwaltung/barkaution/C9NS3gndTEXrX6CoHIyGy",
                      "type": "INDIVIDUAL",
                      "givenReference": "M03879.Obj0842",
                      "sourceId": "pm-2024-unit-789",
                      "tenants": [
                        {
                          "firstName": "Max",
                          "lastName": "Mustermann"
                        }
                      ],
                      "streetName": "Hauptstraße",
                      "streetNumber": "123",
                      "postalCode": "10115",
                      "region": "Berlin",
                      "countryCode": "DE",
                      "depositAmountCents": 150000
                    },
                    {
                      "id": "MCAtSsrg4gjYK1b9NnZia",
                      "createdAt": "2025-09-28T11:45:00+02:00",
                      "updatedAt": "2025-10-18T09:30:00+02:00",
                      "iban": "DE89370400440532013001",
                      "appLink": "https://getmomo.app/kautionsverwaltung/barkaution/MCAtSsrg4gjYK1b9NnZia",
                      "type": "COMPANY",
                      "givenReference": "M03880.Obj0843",
                      "sourceId": "pm-2024-unit-789",
                      "tenants": [
                        {
                          "companyName": "Mustermann GmbH",
                          "companyDirectors": [
                            {
                              "firstName": "Max",
                              "lastName": "Mustermann"
                            }
                          ]
                        }
                      ],
                      "streetName": "Nebenstraße",
                      "streetNumber": "456",
                      "postalCode": "10117",
                      "region": "Berlin",
                      "countryCode": "DE",
                      "depositAmountCents": 200000
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      },
      "post": {
        "summary": "Create virtual deposit account",
        "description": "Creates a new virtual deposit account for individual tenant(s) or company tenant. Use the 'type' field to specify which type to create.",
        "operationId": "createVirtualDepositAccount",
        "tags": ["Virtual Deposit Accounts"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "depositAccountId",
            "in": "path",
            "required": true,
            "description": "The unique identifier of the deposit account",
            "schema": {
              "type": "string"
            },
            "example": "EQ4Npb2K_yTUch0oIKWZH"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateVirtualDepositAccountRequest"
              },
              "examples": {
                "individual": {
                  "summary": "Individual tenant(s) example",
                  "value": {
                    "type": "INDIVIDUAL",
                    "givenReference": "M03879.Obj0842",
                    "sourceId": "pm-2024-unit-789",
                    "tenants": [
                      {
                        "firstName": "Max",
                        "lastName": "Mustermann"
                      },
                      {
                        "firstName": "Erika",
                        "lastName": "Musterfrau"
                      }
                    ],
                    "streetName": "Hauptstraße",
                    "streetNumber": "123",
                    "postalCode": "10115",
                    "region": "Berlin",
                    "countryCode": "DE",
                    "depositAmountCents": 200000
                  }
                },
                "company": {
                  "summary": "Company tenant example",
                  "value": {
                    "type": "COMPANY",
                    "givenReference": "M03879.Obj0842",
                    "sourceId": "pm-2024-unit-789",
                    "tenants": [
                      {
                        "companyName": "Mustermann GmbH",
                        "companyDirectors": [
                          {
                            "firstName": "Max",
                            "lastName": "Mustermann"
                          },
                          {
                            "firstName": "Erika",
                            "lastName": "Musterfrau"
                          }
                        ]
                      }
                    ],
                    "streetName": "Hauptstraße",
                    "streetNumber": "123",
                    "postalCode": "10115",
                    "region": "Berlin",
                    "countryCode": "DE",
                    "depositAmountCents": 150000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Virtual deposit account created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VirtualDepositAccount"
                },
                "examples": {
                  "individual": {
                    "summary": "Individual tenant response",
                    "value": {
                      "id": "C9NS3gndTEXrX6CoHIyGy",
                      "createdAt": "2025-10-23T11:00:00+02:00",
                      "updatedAt": "2025-10-23T11:00:00+02:00",
                      "iban": "DE89370400440532013000",
                      "appLink": "https://getmomo.app/kautionsverwaltung/barkaution/C9NS3gndTEXrX6CoHIyGy",
                      "type": "INDIVIDUAL",
                      "givenReference": "M03879.Obj0842",
                      "sourceId": "pm-2024-unit-789",
                      "tenants": [
                        {
                          "firstName": "Max",
                          "lastName": "Mustermann"
                        }
                      ],
                      "streetName": "Hauptstraße",
                      "streetNumber": "123",
                      "postalCode": "10115",
                      "region": "Berlin",
                      "countryCode": "DE",
                      "depositAmountCents": 150000
                    }
                  },
                  "company": {
                    "summary": "Company tenant response",
                    "value": {
                      "id": "MCAtSsrg4gjYK1b9NnZia",
                      "createdAt": "2025-10-24T09:30:00+02:00",
                      "updatedAt": "2025-10-24T09:30:00+02:00",
                      "iban": "DE89370400440532013000",
                      "appLink": "https://getmomo.app/kautionsverwaltung/barkaution/MCAtSsrg4gjYK1b9NnZia",
                      "type": "COMPANY",
                      "givenReference": "M03879.Obj0842",
                      "sourceId": "pm-2024-unit-789",
                      "tenants": [
                        {
                          "companyName": "Mustermann GmbH",
                          "companyDirectors": [
                            {
                              "firstName": "Max",
                              "lastName": "Mustermann"
                            }
                          ]
                        }
                      ],
                      "streetName": "Hauptstraße",
                      "streetNumber": "123",
                      "postalCode": "10115",
                      "region": "Berlin",
                      "countryCode": "DE",
                      "depositAmountCents": 150000
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/deposit-account/{depositAccountId}/virtual/{virtualDepositAccountId}": {
      "get": {
        "summary": "Get a single virtual deposit account",
        "description": "Retrieves a single virtual deposit account by its unique identifier",
        "operationId": "getVirtualDepositAccount",
        "tags": ["Virtual Deposit Accounts"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "depositAccountId",
            "in": "path",
            "required": true,
            "description": "The unique identifier of the deposit account",
            "schema": {
              "type": "string"
            },
            "example": "iDVh8yNUQ8y2hh1jkXTbi"
          },
          {
            "name": "virtualDepositAccountId",
            "in": "path",
            "required": true,
            "description": "The unique identifier of the virtual deposit account",
            "schema": {
              "type": "string"
            },
            "example": "C9NS3gndTEXrX6CoHIyGy"
          }
        ],
        "responses": {
          "200": {
            "description": "Virtual deposit account retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VirtualDepositAccount"
                },
                "example": {
                  "id": "C9NS3gndTEXrX6CoHIyGy",
                  "createdAt": "2025-09-25T10:30:00+02:00",
                  "updatedAt": "2025-10-15T14:20:00+02:00",
                  "iban": "DE89370400440532013000",
                  "appLink": "https://getmomo.app/kautionsverwaltung/barkaution/C9NS3gndTEXrX6CoHIyGy",
                  "type": "INDIVIDUAL",
                  "givenReference": "M03879.Obj0842",
                  "sourceId": "pm-2024-unit-789",
                  "tenants": [
                    {
                      "firstName": "Max",
                      "lastName": "Mustermann"
                    }
                  ],
                  "streetName": "Hauptstraße",
                  "streetNumber": "123",
                  "postalCode": "10115",
                  "region": "Berlin",
                  "countryCode": "DE",
                  "depositAmountCents": 150000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/deposit-account/{depositAccountId}/virtual/{virtualDepositAccountId}/balance": {
      "get": {
        "summary": "Get virtual deposit account balance",
        "description": "Retrieves the current balance of a virtual deposit account",
        "operationId": "getVirtualDepositAccountBalance",
        "tags": ["Virtual Deposit Accounts"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "depositAccountId",
            "in": "path",
            "required": true,
            "description": "The unique identifier of the deposit account",
            "schema": {
              "type": "string"
            },
            "example": "uYfXVMXfUrTkv2vT4xZel"
          },
          {
            "name": "virtualDepositAccountId",
            "in": "path",
            "required": true,
            "description": "The unique identifier of the virtual deposit account",
            "schema": {
              "type": "string"
            },
            "example": "vKo8sCA4VWbTNk8msiqPA"
          }
        ],
        "responses": {
          "200": {
            "description": "Balance retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BalanceResponse"
                },
                "example": {
                  "amountCents": 150000,
                  "currency": "EUR",
                  "updatedAt": "2025-10-23T14:30:00+02:00"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    }
  },
  "webhooks": {
    "test": {
      "post": {
        "summary": "Test Event",
        "description": "Sent when a test event is triggered from the Manager App. Use this to verify your webhook endpoint is correctly configured and can validate signatures.",
        "operationId": "webhookTestEvent",
        "tags": ["Webhooks"],
        "parameters": [
          {
            "name": "X-Getmomo-Signature",
            "in": "header",
            "required": true,
            "description": "HMAC-SHA256 signature of the request body. Format: `v1,<base64-encoded-signature>`",
            "schema": {
              "type": "string"
            },
            "example": "v1,K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols="
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookTestEvent"
              },
              "example": {
                "type": "TEST",
                "payload": {
                  "triggered_at": "2026-03-26T12:00:00.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Return any 2xx status to acknowledge receipt"
          }
        }
      }
    },
    "virtualDepositAccountBalanceUpdated": {
      "post": {
        "summary": "Virtual Deposit Account Balance Updated",
        "description": "Sent whenever the balance of a virtual deposit account changes. Use this to keep your system in sync with deposit balances managed by Momo. Delivery is retried with exponential backoff on failure; after the final unsuccessful retry, the webhook is automatically disabled and the manager is notified by email.",
        "operationId": "webhookVirtualDepositAccountBalanceUpdatedEvent",
        "tags": ["Webhooks"],
        "parameters": [
          {
            "name": "X-Getmomo-Signature",
            "in": "header",
            "required": true,
            "description": "HMAC-SHA256 signature of the request body. Format: `v1,<base64-encoded-signature>`",
            "schema": {
              "type": "string"
            },
            "example": "v1,K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols="
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookVirtualDepositAccountBalanceUpdatedEvent"
              },
              "example": {
                "type": "VIRTUAL_DEPOSIT_ACCOUNT_BALANCE_UPDATED",
                "payload": {
                  "depositAccountId": "deposit-account-abc123",
                  "virtualDepositAccountId": "virtual-deposit-account-def456",
                  "amountCents": 150000,
                  "currency": "EUR",
                  "updatedAt": "2026-04-07T12:00:00.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Return any 2xx status to acknowledge receipt"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Bearer token authentication. Include the token in the Authorization header as 'Bearer {token}'"
      }
    },
    "schemas": {
      "CreateVirtualDepositAccountRequestBase": {
        "type": "object",
        "required": [
          "streetName",
          "streetNumber",
          "postalCode",
          "region",
          "countryCode",
          "depositAmountCents"
        ],
        "properties": {
          "givenReference": {
            "type": "string",
            "description": "Optional reference for the tenancy. We recommend a combination of the tenancy agreement number and property number (e.g. M03879.Obj0842)",
            "example": "M03879.Obj0842"
          },
          "sourceId": {
            "type": "string",
            "description": "Optional identifier from your own system. Use this to link the virtual deposit account to records in your property management software or internal database",
            "example": "pm-2024-unit-789"
          },
          "streetName": {
            "type": "string",
            "description": "Street name of the rental property",
            "example": "Hauptstraße"
          },
          "streetNumber": {
            "type": "string",
            "description": "Street number of the rental property",
            "example": "123"
          },
          "postalCode": {
            "type": "string",
            "description": "Postal code of the rental property",
            "example": "10115"
          },
          "region": {
            "type": "string",
            "description": "Region/state of the rental property",
            "example": "Berlin"
          },
          "countryCode": {
            "type": "string",
            "enum": ["DE"],
            "description": "Country code. Only 'DE' (Deutschland) is accepted as we only support German addresses",
            "example": "DE"
          },
          "depositAmountCents": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "description": "Deposit amount in cents. Must be a positive integer",
            "example": 150000
          },
          "rentalContractStartDate": {
            "type": "string",
            "format": "date",
            "description": "Optional start date of the rental contract (ISO 8601 date format, e.g. 2025-01-01)",
            "example": "2025-01-01"
          }
        }
      },
      "CreateVirtualDepositAccountIndividualRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CreateVirtualDepositAccountRequestBase"
          },
          {
            "type": "object",
            "required": ["type", "tenants"],
            "properties": {
              "type": {
                "type": "string",
                "enum": ["INDIVIDUAL"],
                "description": "Type of virtual deposit account. Must be 'INDIVIDUAL'",
                "example": "INDIVIDUAL"
              },
              "tenants": {
                "type": "array",
                "minItems": 1,
                "maxItems": 2,
                "items": {
                  "$ref": "#/components/schemas/IndividualTenant"
                },
                "description": "Array of individual tenants (minimum 1, maximum 2)",
                "example": [
                  {
                    "firstName": "Max",
                    "lastName": "Mustermann"
                  }
                ]
              }
            }
          }
        ]
      },
      "CreateVirtualDepositAccountCompanyRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CreateVirtualDepositAccountRequestBase"
          },
          {
            "type": "object",
            "required": ["type", "tenants"],
            "properties": {
              "type": {
                "type": "string",
                "enum": ["COMPANY"],
                "description": "Type of virtual deposit account. Must be 'COMPANY'",
                "example": "COMPANY"
              },
              "tenants": {
                "type": "array",
                "minItems": 1,
                "maxItems": 1,
                "items": {
                  "$ref": "#/components/schemas/CompanyTenant"
                },
                "description": "Array of company tenants (exactly 1 required)",
                "example": [
                  {
                    "companyName": "Tech Startup GmbH",
                    "companyDirectors": [
                      {
                        "firstName": "Anna",
                        "lastName": "Schmidt"
                      }
                    ]
                  }
                ]
              }
            }
          }
        ]
      },
      "CreateVirtualDepositAccountRequest": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/CreateVirtualDepositAccountIndividualRequest"
          },
          {
            "$ref": "#/components/schemas/CreateVirtualDepositAccountCompanyRequest"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "INDIVIDUAL": "#/components/schemas/CreateVirtualDepositAccountIndividualRequest",
            "COMPANY": "#/components/schemas/CreateVirtualDepositAccountCompanyRequest"
          }
        }
      },
      "IndividualTenant": {
        "type": "object",
        "required": ["firstName", "lastName"],
        "properties": {
          "firstName": {
            "type": "string",
            "description": "First name of the tenant",
            "example": "Max"
          },
          "lastName": {
            "type": "string",
            "description": "Last name of the tenant",
            "example": "Mustermann"
          },
          "dateOfBirth": {
            "type": "string",
            "format": "date",
            "description": "Date of birth of the tenant (ISO 8601 date format: YYYY-MM-DD). It is highly encouraged to always provide the tenant date of birth to avoid follow-up queries for this information from our partner bank.",
            "example": "1990-05-15"
          }
        }
      },
      "CompanyTenant": {
        "type": "object",
        "required": ["companyName", "companyDirectors"],
        "properties": {
          "companyName": {
            "type": "string",
            "description": "Name of the company",
            "example": "Mustermann GmbH"
          },
          "companyDirectors": {
            "type": "array",
            "minItems": 1,
            "maxItems": 3,
            "items": {
              "$ref": "#/components/schemas/CompanyDirector"
            },
            "description": "Array of company directors (minimum 1, maximum 3)",
            "example": [
              {
                "firstName": "Max",
                "lastName": "Mustermann"
              }
            ]
          }
        }
      },
      "CompanyDirector": {
        "type": "object",
        "required": ["firstName", "lastName"],
        "properties": {
          "firstName": {
            "type": "string",
            "description": "First name of the company director",
            "example": "Max"
          },
          "lastName": {
            "type": "string",
            "description": "Last name of the company director",
            "example": "Mustermann"
          }
        }
      },
      "EntityBase": {
        "type": "object",
        "required": ["id", "createdAt"],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier for the entity",
            "example": "vWRaPWn3iIDr8iBpdAHpW"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the entity was created (ISO 8601 with timezone)",
            "example": "2025-10-23T10:00:00+02:00"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the entity was last updated (ISO 8601 with timezone)",
            "example": "2025-10-23T14:30:00+02:00"
          }
        }
      },
      "VirtualDepositAccountBase": {
        "allOf": [
          {
            "$ref": "#/components/schemas/EntityBase"
          },
          {
            "type": "object",
            "required": [
              "iban",
              "appLink",
              "type",
              "streetName",
              "streetNumber",
              "postalCode",
              "region",
              "countryCode",
              "depositAmountCents"
            ],
            "properties": {
              "iban": {
                "type": "string",
                "pattern": "^[A-Z]{2}[0-9]{2}[A-Z0-9]+$",
                "description": "The virtual IBAN allocated to this virtual deposit account",
                "example": "DE89370400440532013000"
              },
              "appLink": {
                "type": "string",
                "format": "uri",
                "description": "Deep link to this virtual deposit account in the Manager App",
                "example": "https://getmomo.app/kautionsverwaltung/barkaution/C9NS3gndTEXrX6CoHIyGy"
              },
              "type": {
                "type": "string",
                "enum": ["INDIVIDUAL", "COMPANY"],
                "description": "Type of tenant for this virtual deposit account"
              },
              "givenReference": {
                "type": "string",
                "description": "Optional reference for the tenancy. We recommend a combination of the tenancy agreement number and property number (e.g. M03879.Obj0842)",
                "example": "M03879.Obj0842"
              },
              "sourceId": {
                "type": "string",
                "description": "Optional identifier from your own system. Use this to link the virtual deposit account to records in your property management software or internal database",
                "example": "pm-2024-unit-789"
              },
              "streetName": {
                "type": "string",
                "description": "Street name of the rental property",
                "example": "Hauptstraße"
              },
              "streetNumber": {
                "type": "string",
                "description": "Street number of the rental property",
                "example": "123"
              },
              "postalCode": {
                "type": "string",
                "description": "Postal code of the rental property",
                "example": "10115"
              },
              "region": {
                "type": "string",
                "description": "Region/state of the rental property",
                "example": "Berlin"
              },
              "countryCode": {
                "type": "string",
                "enum": ["DE"],
                "description": "Country code. Only 'DE' (Deutschland) is accepted as we only support German addresses",
                "example": "DE"
              },
              "depositAmountCents": {
                "type": "integer",
                "exclusiveMinimum": 0,
                "description": "Deposit amount in cents. Must be a positive integer",
                "example": 150000
              },
              "rentalContractStartDate": {
                "type": "string",
                "format": "date",
                "description": "Optional start date of the rental contract (ISO 8601 date format, e.g. 2025-01-01)",
                "example": "2025-01-01"
              }
            }
          }
        ]
      },
      "VirtualDepositAccountIndividual": {
        "allOf": [
          {
            "$ref": "#/components/schemas/VirtualDepositAccountBase"
          },
          {
            "type": "object",
            "required": ["tenants"],
            "properties": {
              "type": {
                "type": "string",
                "enum": ["INDIVIDUAL"]
              },
              "tenants": {
                "type": "array",
                "minItems": 1,
                "maxItems": 2,
                "items": {
                  "$ref": "#/components/schemas/IndividualTenant"
                },
                "description": "Array of tenants (minimum 1, maximum 2)"
              }
            }
          }
        ]
      },
      "VirtualDepositAccountCompany": {
        "allOf": [
          {
            "$ref": "#/components/schemas/VirtualDepositAccountBase"
          },
          {
            "type": "object",
            "required": ["tenants"],
            "properties": {
              "type": {
                "type": "string",
                "enum": ["COMPANY"]
              },
              "tenants": {
                "type": "array",
                "minItems": 1,
                "maxItems": 1,
                "items": {
                  "$ref": "#/components/schemas/CompanyTenant"
                },
                "description": "Array of company tenants (exactly 1 required)"
              }
            }
          }
        ]
      },
      "VirtualDepositAccount": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/VirtualDepositAccountIndividual"
          },
          {
            "$ref": "#/components/schemas/VirtualDepositAccountCompany"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "INDIVIDUAL": "#/components/schemas/VirtualDepositAccountIndividual",
            "COMPANY": "#/components/schemas/VirtualDepositAccountCompany"
          }
        }
      },
      "BalanceResponse": {
        "type": "object",
        "required": ["amountCents", "currency"],
        "properties": {
          "amountCents": {
            "type": "integer",
            "description": "Current balance in cents",
            "example": 150000
          },
          "currency": {
            "type": "string",
            "enum": ["EUR"],
            "description": "Currency of the balance",
            "example": "EUR"
          },
          "updatedAt": {
            "type": ["string", "null"],
            "format": "date-time",
            "description": "Timestamp when the balance was last updated (ISO 8601 with timezone). Null if no transactions have occurred.",
            "example": "2025-10-23T14:30:00+02:00"
          }
        }
      },
      "DepositAccount": {
        "allOf": [
          {
            "$ref": "#/components/schemas/EntityBase"
          },
          {
            "type": "object",
            "required": ["name", "iban", "bic", "isDefault"],
            "properties": {
              "name": {
                "type": "string",
                "description": "Name of the deposit account",
                "example": "Main Deposit Account"
              },
              "title": {
                "type": "string",
                "description": "Optional title for the deposit account",
                "example": "Primary Account"
              },
              "iban": {
                "type": "string",
                "pattern": "^[A-Z]{2}[0-9]{2}[A-Z0-9]+$",
                "description": "IBAN of the deposit account",
                "example": "DE89370400440532013000"
              },
              "bic": {
                "type": "string",
                "description": "BIC/SWIFT code of the deposit account",
                "example": "HSHNDEHHXXX"
              },
              "isDefault": {
                "type": "boolean",
                "description": "Indicates whether this is the default deposit account.",
                "example": true
              }
            }
          }
        ]
      },
      "PaginationMetadata": {
        "type": "object",
        "required": ["offset", "limit", "totalItems"],
        "properties": {
          "offset": {
            "type": "integer",
            "minimum": 0,
            "description": "Number of items skipped before these results",
            "example": 0
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "description": "Maximum number of items returned in this response",
            "example": 15
          },
          "totalItems": {
            "type": "integer",
            "minimum": 0,
            "description": "Total number of items available",
            "example": 42
          }
        }
      },
      "DepositAccountListResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/PaginationMetadata"
          },
          {
            "type": "object",
            "required": ["items"],
            "properties": {
              "items": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/DepositAccount"
                },
                "description": "List of deposit accounts for the current page"
              }
            }
          }
        ]
      },
      "VirtualDepositAccountListResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/PaginationMetadata"
          },
          {
            "type": "object",
            "required": ["items"],
            "properties": {
              "items": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/VirtualDepositAccount"
                },
                "description": "List of virtual deposit accounts for the current page"
              }
            }
          }
        ]
      },
      "WebhookTestPayload": {
        "type": "object",
        "required": ["triggered_at"],
        "properties": {
          "triggered_at": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the test event was triggered (ISO 8601 with timezone)",
            "example": "2026-03-26T12:00:00.000Z"
          }
        }
      },
      "WebhookTestEvent": {
        "type": "object",
        "required": ["type", "payload"],
        "properties": {
          "type": {
            "type": "string",
            "enum": ["TEST"],
            "description": "Event type identifier"
          },
          "payload": {
            "$ref": "#/components/schemas/WebhookTestPayload"
          }
        }
      },
      "WebhookVirtualDepositAccountBalanceUpdatedPayload": {
        "type": "object",
        "required": [
          "depositAccountId",
          "virtualDepositAccountId",
          "amountCents",
          "currency",
          "updatedAt"
        ],
        "properties": {
          "depositAccountId": {
            "type": "string",
            "description": "Identifier of the parent deposit account",
            "example": "deposit-account-abc123"
          },
          "virtualDepositAccountId": {
            "type": "string",
            "description": "Identifier of the virtual deposit account whose balance changed",
            "example": "virtual-deposit-account-def456"
          },
          "amountCents": {
            "type": "integer",
            "description": "New balance in cents",
            "example": 150000
          },
          "currency": {
            "type": "string",
            "enum": ["EUR"],
            "description": "ISO 4217 currency code",
            "example": "EUR"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the balance was updated (ISO 8601 with timezone)",
            "example": "2026-04-07T12:00:00.000Z"
          }
        }
      },
      "WebhookVirtualDepositAccountBalanceUpdatedEvent": {
        "type": "object",
        "required": ["type", "payload"],
        "properties": {
          "type": {
            "type": "string",
            "enum": ["VIRTUAL_DEPOSIT_ACCOUNT_BALANCE_UPDATED"],
            "description": "Event type identifier"
          },
          "payload": {
            "$ref": "#/components/schemas/WebhookVirtualDepositAccountBalanceUpdatedPayload"
          }
        }
      },
      "WebhookEvent": {
        "type": "object",
        "required": ["type", "payload"],
        "description": "Common envelope for all webhook events. The `type` field determines the shape of `payload`.",
        "properties": {
          "type": {
            "type": "string",
            "enum": ["TEST", "VIRTUAL_DEPOSIT_ACCOUNT_BALANCE_UPDATED"],
            "description": "Event type identifier"
          },
          "payload": {
            "type": "object",
            "description": "Event-specific payload. Shape depends on the event type."
          }
        },
        "oneOf": [
          {
            "$ref": "#/components/schemas/WebhookTestEvent"
          },
          {
            "$ref": "#/components/schemas/WebhookVirtualDepositAccountBalanceUpdatedEvent"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "TEST": "#/components/schemas/WebhookTestEvent",
            "VIRTUAL_DEPOSIT_ACCOUNT_BALANCE_UPDATED": "#/components/schemas/WebhookVirtualDepositAccountBalanceUpdatedEvent"
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "required": ["code", "message"],
        "properties": {
          "code": {
            "type": "string",
            "description": "Machine-readable error code",
            "example": "VALIDATION_ERROR"
          },
          "message": {
            "type": "string",
            "description": "Human-readable error message",
            "example": "The request contains invalid data"
          },
          "details": {
            "type": "object",
            "description": "Additional error details, such as field-specific validation errors",
            "additionalProperties": true,
            "example": {
              "tenants[0].firstName": "This field is required",
              "depositAmountCents": "Must be a positive number"
            }
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Bad Request - Invalid input data or validation errors",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "validationError": {
                "summary": "Validation error example",
                "value": {
                  "code": "VALIDATION_ERROR",
                  "message": "The request contains invalid data",
                  "details": {
                    "tenants[0].firstName": "This field is required",
                    "depositAmountCents": "Must be a positive number"
                  }
                }
              },
              "conditionalFieldError": {
                "summary": "Conditional field validation error",
                "value": {
                  "code": "VALIDATION_ERROR",
                  "message": "The request contains invalid data",
                  "details": {
                    "tenants[1].lastName": "This field is required when tenants[1].firstName is provided"
                  }
                }
              }
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Unauthorized - Missing or invalid Bearer token",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "code": "UNAUTHORIZED",
              "message": "Authentication required. Please provide a valid Bearer token"
            }
          }
        }
      },
      "NotFound": {
        "description": "Not Found - The requested resource does not exist",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "depositAccountNotFound": {
                "summary": "Deposit account not found",
                "value": {
                  "code": "NOT_FOUND",
                  "message": "Deposit account not found",
                  "details": {
                    "depositAccountId": "da_123456789"
                  }
                }
              },
              "virtualDepositAccountNotFound": {
                "summary": "Virtual deposit account not found",
                "value": {
                  "code": "NOT_FOUND",
                  "message": "Virtual deposit account not found",
                  "details": {
                    "depositAccountId": "da_123456789",
                    "virtualDepositAccountId": "vda_987654321"
                  }
                }
              }
            }
          }
        }
      },
      "Conflict": {
        "description": "Conflict - The request conflicts with the current state (e.g., duplicate account)",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "duplicateSourceId": {
                "summary": "Duplicate source ID",
                "value": {
                  "code": "CONFLICT",
                  "message": "A virtual deposit account with this source ID already exists",
                  "details": {
                    "depositAccountId": "da_123456789",
                    "sourceId": "external_ref_123"
                  }
                }
              },
              "noAvailableVibans": {
                "summary": "No available virtual IBANs",
                "value": {
                  "code": "CONFLICT",
                  "message": "No available virtual IBANs for this deposit account. Please contact support.",
                  "details": {
                    "depositAccountId": "da_123456789"
                  }
                }
              }
            }
          }
        }
      },
      "InternalServerError": {
        "description": "Internal Server Error - An unexpected error occurred on the server",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "code": "INTERNAL_SERVER_ERROR",
              "message": "An unexpected error occurred. Please try again later"
            }
          }
        }
      },
      "PayloadTooLarge": {
        "description": "Payload Too Large - The request body exceeds the maximum allowed size (100KB)",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "code": "PAYLOAD_TOO_LARGE",
              "message": "Request payload too large"
            }
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Deposit Accounts",
      "description": "Endpoints for managing deposit accounts"
    },
    {
      "name": "Virtual Deposit Accounts",
      "description": "Endpoints for managing virtual deposit accounts for rental properties"
    },
    {
      "name": "Webhooks",
      "description": "Webhook events delivered to your registered endpoint.\n\n## Setting Up a Webhook\n\n1. In the Manager App, navigate to **[Integrationen](https://getmomo.app/integrationen)** (Integrations).\n\n<img src=\"assets/img/webhooks-doc/01_page_integrations.png\" alt=\"Integrations page\" width=\"600\" />\n\n2. Open the **Offene Schnittstelle** (Public API) integration card, then select the **Webhooks** tab and click **Neuen Webhook erstellen** (Create new webhook) to register your endpoint URL and set a signing secret.\n\n<img src=\"assets/img/webhooks-doc/02_page_integrations_public_api_webhooks.png\" alt=\"Webhooks tab\" width=\"600\" />\n\n## Signature Verification\n\nEvery webhook request includes an `X-Getmomo-Signature` header for verifying authenticity. The signature is an HMAC-SHA256 digest of the raw JSON request body, computed with your webhook secret.\n\n**Header format:** `v1,<base64-encoded-signature>`\n\n**Verification examples:**\n\n### Node.js / TypeScript\n```typescript\nimport crypto from 'node:crypto';\n\nfunction verifySignature(secret: string, body: string, header: string): boolean {\n  const signature = crypto.createHmac('sha256', secret).update(body).digest('base64');\n  const expected = `v1,${signature}`;\n  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(header));\n}\n```\n\n### Python\n```python\nimport hmac\nimport hashlib\nimport base64\n\ndef verify_signature(secret: str, body: bytes, header: str) -> bool:\n    signature = base64.b64encode(\n        hmac.new(secret.encode(), body, hashlib.sha256).digest()\n    ).decode()\n    expected = f\"v1,{signature}\"\n    return hmac.compare_digest(expected, header)\n```\n\n### Go\n```go\nimport (\n  \"crypto/hmac\"\n  \"crypto/sha256\"\n  \"encoding/base64\"\n  \"fmt\"\n)\n\nfunc VerifySignature(secret, body, header string) bool {\n  mac := hmac.New(sha256.New, []byte(secret))\n  mac.Write([]byte(body))\n  expected := fmt.Sprintf(\"v1,%s\", base64.StdEncoding.EncodeToString(mac.Sum(nil)))\n  return hmac.Equal([]byte(expected), []byte(header))\n}\n```\n\n### C#\n```csharp\nusing System.Security.Cryptography;\nusing System.Text;\n\npublic static bool VerifySignature(string secret, string body, string header)\n{\n    using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret));\n    var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(body));\n    var expected = $\"v1,{Convert.ToBase64String(hash)}\";\n    return CryptographicOperations.FixedTimeEquals(\n        Encoding.UTF8.GetBytes(expected),\n        Encoding.UTF8.GetBytes(header)\n    );\n}\n```\n\n### Java\n```java\nimport javax.crypto.Mac;\nimport javax.crypto.spec.SecretKeySpec;\nimport java.security.MessageDigest;\nimport java.util.Base64;\n\npublic static boolean verifySignature(String secret, String body, String header) throws Exception {\n    Mac mac = Mac.getInstance(\"HmacSHA256\");\n    mac.init(new SecretKeySpec(secret.getBytes(\"UTF-8\"), \"HmacSHA256\"));\n    String signature = Base64.getEncoder().encodeToString(mac.doFinal(body.getBytes(\"UTF-8\")));\n    String expected = \"v1,\" + signature;\n    return MessageDigest.isEqual(expected.getBytes(\"UTF-8\"), header.getBytes(\"UTF-8\"));\n}\n```\n\n### Ruby\n```ruby\nrequire 'openssl'\nrequire 'base64'\n\ndef verify_signature(secret, body, header)\n  signature = Base64.strict_encode64(\n    OpenSSL::HMAC.digest('sha256', secret, body)\n  )\n  expected = \"v1,#{signature}\"\n  Rack::Utils.secure_compare(expected, header)\nend\n```\n\n### PHP\n```php\nfunction verifySignature(string $secret, string $body, string $header): bool {\n    $signature = base64_encode(hash_hmac('sha256', $body, $secret, true));\n    $expected = \"v1,{$signature}\";\n    return hash_equals($expected, $header);\n}\n```\n\nAlways use a constant-time comparison function to prevent timing attacks.\n\n## Delivery Behavior\n\n- Events are delivered as `POST` requests with `Content-Type: application/json`\n- Your endpoint must respond with a `2xx` status code to acknowledge receipt\n- On repeated failure (non-2xx or network error), the webhook is **disabled** and an email notification is sent to all managers with webhook management permissions\n- Re-enable a disabled webhook from the Manager App after resolving the issue\n\n## Event Envelope\n\nAll events share a common envelope:\n\n```json\n{\n  \"type\": \"<EVENT_TYPE>\",\n  \"payload\": { ... }\n}\n```\n\nThe `type` field identifies the event. The `payload` shape depends on the event type."
    }
  ]
}
