Download OpenAPI specification:Download (JSON)
Public API for interfacing with the Getmomo service offering.
This API supports both request/response endpoints and webhook event delivery. See the Webhooks section for details on event types, payload schemas, and signature verification.
Every error response carries code, message and, on every status except 500, errorCode. code restates the HTTP status and takes exactly one value per status. errorCode is the semantic discriminator a client branches on. Each operation lists the errorCode values it can return under its own error responses; there is no single global list, because the set is operation-specific. details carries structured context whose keys depend on the errorCode.
Writes are strongly consistent. A POST, PATCH or DELETE commits before it responds, and its response body reflects the state it wrote.
GET and list endpoints serve a read model that is rebuilt in the background after each write. The rebuild is normally sub-second, sometimes a few seconds. It runs as a chain of background jobs that retry with exponential backoff, so a failing job stretches the window. Inside that window a read returns the state from before the write.
getVirtualDepositAccountBalance is exempt. It reads the ledger directly and reflects a write as soon as the write returns.
The version tokens in a write response (version, rentalContractVersion, per-tenant version) are current and safe to use for the next write. A GET issued between two of your own writes returns the pre-write tokens. Sending those back produces a 409 CONFLICT with errorCode VERSION_CONFLICT, TENANT_VERSION_CONFLICT or PROPERTY_OWNER_VERSION_CONFLICT, with no concurrent writer involved.
Round-trip the version tokens from the previous write's response body. Take a token from a GET only when you have no write of your own in flight.
Retrieves all deposit accounts with pagination support
| offset | integer >= 0 Default: 0 Example: offset=15 Number of items to skip before returning results |
| limit | integer [ 1 .. 100 ] Default: 15 Example: limit=15 Maximum number of items to return |
| offset required | integer >= 0 Number of items skipped before these results |
| limit required | integer [ 1 .. 100 ] Maximum number of items returned in this response |
| totalItems required | integer >= 0 Total number of items available |
required | Array of objects (DepositAccount) List of deposit accounts for the current page |
{- "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",
- "version": "5",
- "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",
- "version": "2",
- "name": "Property Management GmbH",
- "iban": "DE89370400440532013001",
- "bic": "HSHNDEHHXXX",
- "isDefault": false
}
]
}Retrieves a single deposit account by its unique identifier
| depositAccountId required | string Example: q3a2bQPpNz2tu4nkTrjmI The unique identifier of the deposit account |
| id required | string Unique identifier for the entity |
| createdAt required | string <date-time> Timestamp when the entity was created (ISO 8601 with timezone) |
| updatedAt | string <date-time> Timestamp when the entity was last updated (ISO 8601 with timezone) |
| version required | string^[0-9]+$ Opaque optimistic-concurrency token for the entity. Round-trip this value unchanged on mutating requests (PATCH, DELETE) to detect stale writes. Read endpoints lag writes by a short window, so after a write of your own take this token from that write's response body rather than from a |
| name required | string Name of the deposit account |
| title | string Optional title for the deposit account |
| iban required | string^[A-Z]{2}[0-9]{2}[A-Z0-9]+$ IBAN of the deposit account |
| bic required | string BIC/SWIFT code of the deposit account |
| isDefault required | boolean Indicates whether this is the default deposit account. |
{- "id": "q3a2bQPpNz2tu4nkTrjmI",
- "createdAt": "2025-09-10T08:30:00+02:00",
- "updatedAt": "2025-10-23T09:15:00+02:00",
- "version": "7",
- "name": "Property Management GmbH",
- "title": "Primary Account",
- "iban": "DE89370400440532013000",
- "bic": "HSHNDEHHXXX",
- "isDefault": true
}Retrieves all virtual deposit accounts associated with a specific deposit account with pagination support
This list serves a background-rebuilt read model. A freshly created account can be missing, a freshly deleted one can still appear, and a freshly updated one can show its previous field values. See the Consistency section in the API description.
| depositAccountId required | string Example: TgQBfyro4OHY6Iza0zPQa The unique identifier of the deposit account |
| offset | integer >= 0 Default: 0 Example: offset=15 Number of items to skip before returning results |
| limit | integer [ 1 .. 100 ] Default: 15 Example: limit=15 Maximum number of items to return |
| offset required | integer >= 0 Number of items skipped before these results |
| limit required | integer [ 1 .. 100 ] Maximum number of items returned in this response |
| totalItems required | integer >= 0 Total number of items available |
required | Array of any (VirtualDepositAccount) List of virtual deposit accounts for the current page |
{- "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",
- "version": "4",
- "iban": "DE89370400440532013000",
- "type": "INDIVIDUAL",
- "givenReference": "M03879.Obj0842",
- "sourceId": "pm-2024-unit-789",
- "tenants": [
- {
- "firstName": "Max",
- "lastName": "Mustermann",
- "version": "1"
}
], - "streetName": "Hauptstraße",
- "streetNumber": "123",
- "postalCode": "10115",
- "region": "Berlin",
- "countryCode": "DE",
- "depositAmountCents": 150000,
- "notes": "Tenant requested deposit split over two months",
- "payoutNote": null,
- "moveOutDate": null,
- "propertyOwnerId": "vWRaPWn3iIDr8iBpdAHpW",
- "status": "COMPLETE",
- "rentalContractVersion": "3",
- "rentalContractUpdatedAt": "2025-10-20T11:30:00+02:00"
}, - {
- "id": "MCAtSsrg4gjYK1b9NnZia",
- "createdAt": "2025-09-28T11:45:00+02:00",
- "updatedAt": "2025-10-18T09:30:00+02:00",
- "version": "2",
- "iban": "DE89370400440532013001",
- "type": "COMPANY",
- "givenReference": "M03880.Obj0843",
- "sourceId": "pm-2024-unit-789",
- "tenants": [
- {
- "companyName": "Mustermann GmbH",
- "companyDirectors": [
- {
- "firstName": "Max",
- "lastName": "Mustermann",
- "dateOfBirth": "1978-03-22"
}
], - "version": "1"
}
], - "streetName": "Nebenstraße",
- "streetNumber": "456",
- "postalCode": "10117",
- "region": "Berlin",
- "countryCode": "DE",
- "depositAmountCents": 200000,
- "notes": null,
- "payoutNote": null,
- "moveOutDate": null,
- "propertyOwnerId": null,
- "status": "INCOMPLETE",
- "rentalContractVersion": "1",
- "rentalContractUpdatedAt": "2025-10-22T16:45:00+02:00"
}
]
}Creates a new virtual deposit account for individual tenant(s) or company tenant. Use the 'type' field to specify which type to create.
The response body carries the created account and its version tokens. An immediate GET of the new account can return 404 and an immediate list can omit it. See the Consistency section in the API description.
The creation is a durable multi-step operation. Once the request has passed the checks above, it completes even if the connection drops or the service restarts before the response is sent. In that case you receive a transport error or a gateway error, and the account is still created, possibly a few minutes later. An interrupted creation resumes where it stopped and yields exactly one account, with or without a sourceId. Treat such an error as an unknown outcome and retry the request with the same sourceId. A 409 DUPLICATE_SOURCE_ID on the retry confirms the earlier creation. A 201 means the retry performed it. A retry is a new creation and only the sourceId deduplicates it against the interrupted one, so send one whenever the creation must happen exactly once.
| depositAccountId required | string Example: EQ4Npb2K_yTUch0oIKWZH The unique identifier of the deposit account |
| givenReference | string Optional reference for the tenancy. We recommend a combination of the tenancy agreement number and property number (e.g. M03879.Obj0842) |
| sourceId | string Optional identifier from your own system. Use this to link the virtual deposit account to records in your property management software or internal database |
| streetName required | string Street name of the rental property |
| streetNumber required | string Street number of the rental property |
| postalCode required | string Postal code of the rental property |
| region required | string Region/state of the rental property |
| countryCode required | string Value: "DE" Country code. Only 'DE' (Deutschland) is accepted as we only support German addresses |
| depositAmountCents required | integer > 0 Deposit amount in cents. Must be a positive integer |
| rentalContractStartDate | string <date> Optional start date of the rental contract (ISO 8601 date format, e.g. 2025-01-01) |
| notes | string Optional free-text internal notes on the tenancy |
| payoutNote | string Optional note describing the payout / settlement of the deposit |
| moveOutDate | string <date> Optional date the tenant moved out (ISO 8601 date format, e.g. 2025-08-31) |
| propertyOwnerId | string or null Optional identifier of the property owner to assign to this virtual deposit account. A null or omitted value leaves no owner assigned |
| type required | string Type of virtual deposit account. Must be 'INDIVIDUAL' |
required | Array of objects (IndividualTenantInput) [ 1 .. 5 ] items Array of individual tenants (minimum 1, maximum 5) |
| id required | string Unique identifier for the entity |
| createdAt required | string <date-time> Timestamp when the entity was created (ISO 8601 with timezone) |
| updatedAt | string <date-time> Timestamp when the entity was last updated (ISO 8601 with timezone) |
| version required | string^[0-9]+$ Opaque optimistic-concurrency token for the entity. Round-trip this value unchanged on mutating requests (PATCH, DELETE) to detect stale writes. Read endpoints lag writes by a short window, so after a write of your own take this token from that write's response body rather than from a |
| iban required | string^[A-Z]{2}[0-9]{2}[A-Z0-9]+$ The virtual IBAN allocated to this virtual deposit account |
| appLink required | string <uri> Deep link to this virtual deposit account in the Manager App |
| type required | string Type of tenant for this virtual deposit account |
| givenReference | string Optional reference for the tenancy. We recommend a combination of the tenancy agreement number and property number (e.g. M03879.Obj0842) |
| sourceId | string Optional identifier from your own system. Use this to link the virtual deposit account to records in your property management software or internal database |
| streetName required | string Street name of the rental property |
| streetNumber required | string Street number of the rental property |
| postalCode required | string Postal code of the rental property |
| region required | string Region/state of the rental property |
| countryCode required | string Value: "DE" Country code. Only 'DE' (Deutschland) is accepted as we only support German addresses |
| depositAmountCents required | integer > 0 Deposit amount in cents. Must be a positive integer |
| rentalContractStartDate | string <date> Optional start date of the rental contract (ISO 8601 date format, e.g. 2025-01-01) |
| notes required | string or null Free-text internal notes on the tenancy. Null if no notes have been recorded |
| payoutNote required | string or null Note describing the payout / settlement of the deposit. Null if no payout note has been recorded |
| moveOutDate required | string or null <date> Date the tenant moved out (ISO 8601 date format, e.g. 2025-08-31). Null if not set |
| propertyOwnerId required | string or null Identifier of the property owner assigned to this virtual deposit account. Null if no owner is assigned |
| status required | string Enum: "INCOMPLETE" "COMPLETE" "PARTIALLY_PAID_OUT" "RESOLVED" Lifecycle status of the virtual deposit account |
| rentalContractVersion required | string^[0-9]+$ Opaque optimistic-concurrency token for the account's rental contract. It increments whenever a top-level (rental-contract-level) field changes. Round-trip this value unchanged when optimistically locking those fields. |
| rentalContractUpdatedAt | string <date-time> Timestamp when the account's rental contract was last updated (ISO 8601 with timezone). |
required | Array of objects (IndividualTenant) [ 1 .. 5 ] items Array of tenants (minimum 1, maximum 5) |
{- "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
}{- "id": "C9NS3gndTEXrX6CoHIyGy",
- "createdAt": "2025-10-23T11:00:00+02:00",
- "version": "1",
- "iban": "DE89370400440532013000",
- "type": "INDIVIDUAL",
- "givenReference": "M03879.Obj0842",
- "sourceId": "pm-2024-unit-789",
- "tenants": [
- {
- "firstName": "Max",
- "lastName": "Mustermann",
- "version": "1"
}
], - "streetName": "Hauptstraße",
- "streetNumber": "123",
- "postalCode": "10115",
- "region": "Berlin",
- "countryCode": "DE",
- "depositAmountCents": 150000,
- "notes": null,
- "payoutNote": null,
- "moveOutDate": null,
- "propertyOwnerId": null,
- "status": "INCOMPLETE",
- "rentalContractVersion": "2"
}Retrieves a single virtual deposit account by its unique identifier
This endpoint serves a background-rebuilt read model. Right after a create it can return 404, right after a delete it can still return 200, and right after an update it can return the pre-update fields and the pre-update version tokens. See the Consistency section in the API description.
| depositAccountId required | string Example: iDVh8yNUQ8y2hh1jkXTbi The unique identifier of the deposit account |
| virtualDepositAccountId required | string Example: C9NS3gndTEXrX6CoHIyGy The unique identifier of the virtual deposit account |
| id required | string Unique identifier for the entity |
| createdAt required | string <date-time> Timestamp when the entity was created (ISO 8601 with timezone) |
| updatedAt | string <date-time> Timestamp when the entity was last updated (ISO 8601 with timezone) |
| version required | string^[0-9]+$ Opaque optimistic-concurrency token for the entity. Round-trip this value unchanged on mutating requests (PATCH, DELETE) to detect stale writes. Read endpoints lag writes by a short window, so after a write of your own take this token from that write's response body rather than from a |
| iban required | string^[A-Z]{2}[0-9]{2}[A-Z0-9]+$ The virtual IBAN allocated to this virtual deposit account |
| appLink required | string <uri> Deep link to this virtual deposit account in the Manager App |
| type required | string Type of tenant for this virtual deposit account |
| givenReference | string Optional reference for the tenancy. We recommend a combination of the tenancy agreement number and property number (e.g. M03879.Obj0842) |
| sourceId | string Optional identifier from your own system. Use this to link the virtual deposit account to records in your property management software or internal database |
| streetName required | string Street name of the rental property |
| streetNumber required | string Street number of the rental property |
| postalCode required | string Postal code of the rental property |
| region required | string Region/state of the rental property |
| countryCode required | string Value: "DE" Country code. Only 'DE' (Deutschland) is accepted as we only support German addresses |
| depositAmountCents required | integer > 0 Deposit amount in cents. Must be a positive integer |
| rentalContractStartDate | string <date> Optional start date of the rental contract (ISO 8601 date format, e.g. 2025-01-01) |
| notes required | string or null Free-text internal notes on the tenancy. Null if no notes have been recorded |
| payoutNote required | string or null Note describing the payout / settlement of the deposit. Null if no payout note has been recorded |
| moveOutDate required | string or null <date> Date the tenant moved out (ISO 8601 date format, e.g. 2025-08-31). Null if not set |
| propertyOwnerId required | string or null Identifier of the property owner assigned to this virtual deposit account. Null if no owner is assigned |
| status required | string Enum: "INCOMPLETE" "COMPLETE" "PARTIALLY_PAID_OUT" "RESOLVED" Lifecycle status of the virtual deposit account |
| rentalContractVersion required | string^[0-9]+$ Opaque optimistic-concurrency token for the account's rental contract. It increments whenever a top-level (rental-contract-level) field changes. Round-trip this value unchanged when optimistically locking those fields. |
| rentalContractUpdatedAt | string <date-time> Timestamp when the account's rental contract was last updated (ISO 8601 with timezone). |
required | Array of objects (IndividualTenant) [ 1 .. 5 ] items Array of tenants (minimum 1, maximum 5) |
{- "id": "C9NS3gndTEXrX6CoHIyGy",
- "createdAt": "2025-09-25T10:30:00+02:00",
- "updatedAt": "2025-10-15T14:20:00+02:00",
- "version": "3",
- "iban": "DE89370400440532013000",
- "type": "INDIVIDUAL",
- "givenReference": "M03879.Obj0842",
- "sourceId": "pm-2024-unit-789",
- "tenants": [
- {
- "firstName": "Max",
- "lastName": "Mustermann",
- "version": "1"
}
], - "streetName": "Hauptstraße",
- "streetNumber": "123",
- "postalCode": "10115",
- "region": "Berlin",
- "countryCode": "DE",
- "depositAmountCents": 150000,
- "notes": "Tenant requested deposit split over two months",
- "payoutNote": "Deducted EUR 200 for cleaning",
- "moveOutDate": "2025-08-31",
- "propertyOwnerId": "vWRaPWn3iIDr8iBpdAHpW",
- "status": "COMPLETE",
- "rentalContractVersion": "2",
- "rentalContractUpdatedAt": "2025-10-20T11:30:00+02:00"
}Deletes a single virtual deposit account by its unique identifier. The deletion is rejected with a 409 response when the virtual deposit account holds any booked transactions. Deletion requires the current version of the virtual deposit account for optimistic concurrency, so that stale writes are detected. The get virtual deposit account endpoint returns that version. After a write of your own to this account, take the version from that write's response body instead.
Once this operation returns 204 the account is deleted. An immediate GET can still return 200 and an immediate list can still include it. See the Consistency section in the API description.
The deletion is a durable multi-step operation. Once the request has passed the checks above, it completes even if the connection drops or the service restarts before the response is sent. In that case you receive a transport error or a gateway error, and the account is still deleted, possibly a few minutes later. Treat such an error as an unknown outcome and retry the request. A 404 NOT_FOUND on the retry confirms the earlier deletion. A 204 means the retry performed it.
| depositAccountId required | string Example: iDVh8yNUQ8y2hh1jkXTbi The unique identifier of the deposit account |
| virtualDepositAccountId required | string Example: C9NS3gndTEXrX6CoHIyGy The unique identifier of the virtual deposit account |
| version required | string^[0-9]+$ Opaque optimistic-concurrency token of the virtual deposit account. Round-trip this value unchanged to detect stale writes. The deletion is rejected with a version conflict when it does not match the current version. The get virtual deposit account endpoint returns this token. After a write of your own to this account, take it from that write's response body instead, because an immediate read lags the write. |
{- "version": "3"
}{- "code": "BAD_REQUEST",
- "errorCode": "REQUEST_VALIDATION_FAILED",
- "message": "Request validation failed",
- "details": {
- "errors": {
- "version": "Invalid input: expected string, received undefined"
}
}
}Partially updates a virtual deposit account together with its rental contract, tenants and company directors in one call. Only the fields you send change; anything omitted is left as-is. At least one mutable field beyond version and rentalContractVersion must be present, otherwise the request is rejected with 400 BAD_REQUEST / REQUEST_VALIDATION_FAILED.
Every call must carry the current top-level version and rentalContractVersion. Each tenant slot you mutate must carry that tenant's current version. A stale value is rejected with 409 CONFLICT and nothing is written: errorCode is VERSION_CONFLICT or TENANT_VERSION_CONFLICT, and for TENANT_VERSION_CONFLICT details also carries tenantIndex. The response returns the freshly incremented versions of the entities that changed; unchanged entities keep their previous version.
tenants[i] addresses the i-th stored tenant. The array never reorders existing tenants, but a non-null slot at a position beyond the current tenants creates a new tenant (omit version on a creating slot).
tenants entirely to leave all tenants unchanged.{} (or a slot carrying only its version) leaves that position unchanged. Use it to skip earlier tenants when you only want to change a later one:{
"version": "3",
"rentalContractVersion": "5",
"tenants": [
{},
{ "version": "7", "lastName": "Neu" }
]
}
null at a position removes that tenant. Removing a non-trailing tenant compacts the list: survivors keep their relative order and are renumbered 0..n-1. The last remaining tenant cannot be removed; the request is rejected.{
"version": "3",
"rentalContractVersion": "5",
"tenants": [
{},
null
]
}
version and must include firstName and lastName. Creation applies to individual accounts only, up to 5 tenants; a company account always has exactly one company tenant and cannot gain more.{
"version": "3",
"rentalContractVersion": "5",
"tenants": [
{},
{ "firstName": "Neu", "lastName": "Mieter", "dateOfBirth": "1990-05-05" }
]
}
Inside a company slot, companyDirectors fully replaces the stored directors by position. Omit the key to leave directors unchanged. A shorter array removes the trailing directors; a longer one appends. The array must hold 1 to 3 directors, so you cannot clear every director.
Omit propertyOwnerId to leave it unchanged, send null to detach the current owner, or send an id to attach an owner. An id that does not belong to you is rejected with 409 CONFLICT / PROPERTY_OWNER_NOT_FOUND.
Omit notes / payoutNote to leave them unchanged, or send null to clear them.
The response body carries the new state and the current version tokens. An immediate GET of the account can return every mutable field at its pre-update value, and the tokens it returns can be the pre-update ones. Feed the next write from this response body, not from that GET. The top-level version mirrors the deposit and is not changed by this operation. rentalContractVersion and the tenant versions do change. See the Consistency section in the API description.
The update is a durable multi-step operation. Once the request has passed the checks above, it completes even if the connection drops or the service restarts before the response is sent. In that case you receive a transport error or a gateway error, and the update is still applied, possibly a few minutes later. Treat such an error as an unknown outcome and retry the request with the same body and the same version tokens. A 409 CONFLICT with errorCode VERSION_CONFLICT or TENANT_VERSION_CONFLICT on the retry confirms the earlier update; read the current state and tokens with a GET (see Consistency above, it can lag). A 200 means the retry performed it.
| depositAccountId required | string Example: iDVh8yNUQ8y2hh1jkXTbi The unique identifier of the deposit account |
| virtualDepositAccountId required | string Example: C9NS3gndTEXrX6CoHIyGy The unique identifier of the virtual deposit account |
| version required | string^\d+$ Current top-level version of the virtual deposit account, for optimistic locking. |
| rentalContractVersion required | string^\d+$ Current version of the underlying rental contract, for optimistic locking. |
| streetName | string [ 1 .. 200 ] characters Street name of the rental property |
| streetNumber | string [ 1 .. 20 ] characters Street number of the rental property |
| postalCode | string = 5 characters ^\d{5}$ Postal code of the rental property |
| region | string [ 1 .. 100 ] characters Region/state of the rental property |
| depositAmountCents | integer ( 0 .. 1000000000 ] Deposit amount in cents. Must be a positive integer |
| givenReference | string <= 200 characters Reference for the tenancy |
| rentalContractStartDate | string <date> Start date of the rental contract (ISO 8601 date format, e.g. 2025-01-01) |
| moveOutDate | string <date> Date the tenant moved out (ISO 8601 date format, e.g. 2025-08-31) |
| notes | string or null Free-text note. Send |
| payoutNote | string or null Payout note. Send |
| propertyOwnerId | string or null non-empty Property owner id. Omit to leave unchanged, |
Array of (UpdateVirtualDepositAccountTenantSlot (UpdateVirtualDepositAccountIndividualTenantSlot (object) or UpdateVirtualDepositAccountCompanyTenantSlot (object))) or null <= 10 items Positional update of the stored tenants. |
| id required | string Unique identifier for the entity |
| createdAt required | string <date-time> Timestamp when the entity was created (ISO 8601 with timezone) |
| updatedAt | string <date-time> Timestamp when the entity was last updated (ISO 8601 with timezone) |
| version required | string^[0-9]+$ Opaque optimistic-concurrency token for the entity. Round-trip this value unchanged on mutating requests (PATCH, DELETE) to detect stale writes. Read endpoints lag writes by a short window, so after a write of your own take this token from that write's response body rather than from a |
| iban required | string^[A-Z]{2}[0-9]{2}[A-Z0-9]+$ The virtual IBAN allocated to this virtual deposit account |
| appLink required | string <uri> Deep link to this virtual deposit account in the Manager App |
| type required | string Type of tenant for this virtual deposit account |
| givenReference | string Optional reference for the tenancy. We recommend a combination of the tenancy agreement number and property number (e.g. M03879.Obj0842) |
| sourceId | string Optional identifier from your own system. Use this to link the virtual deposit account to records in your property management software or internal database |
| streetName required | string Street name of the rental property |
| streetNumber required | string Street number of the rental property |
| postalCode required | string Postal code of the rental property |
| region required | string Region/state of the rental property |
| countryCode required | string Value: "DE" Country code. Only 'DE' (Deutschland) is accepted as we only support German addresses |
| depositAmountCents required | integer > 0 Deposit amount in cents. Must be a positive integer |
| rentalContractStartDate | string <date> Optional start date of the rental contract (ISO 8601 date format, e.g. 2025-01-01) |
| notes required | string or null Free-text internal notes on the tenancy. Null if no notes have been recorded |
| payoutNote required | string or null Note describing the payout / settlement of the deposit. Null if no payout note has been recorded |
| moveOutDate required | string or null <date> Date the tenant moved out (ISO 8601 date format, e.g. 2025-08-31). Null if not set |
| propertyOwnerId required | string or null Identifier of the property owner assigned to this virtual deposit account. Null if no owner is assigned |
| status required | string Enum: "INCOMPLETE" "COMPLETE" "PARTIALLY_PAID_OUT" "RESOLVED" Lifecycle status of the virtual deposit account |
| rentalContractVersion required | string^[0-9]+$ Opaque optimistic-concurrency token for the account's rental contract. It increments whenever a top-level (rental-contract-level) field changes. Round-trip this value unchanged when optimistically locking those fields. |
| rentalContractUpdatedAt | string <date-time> Timestamp when the account's rental contract was last updated (ISO 8601 with timezone). |
required | Array of objects (IndividualTenant) [ 1 .. 5 ] items Array of tenants (minimum 1, maximum 5) |
{- "version": "3",
- "rentalContractVersion": "5",
- "streetName": "Hauptstraße",
- "streetNumber": "12",
- "postalCode": "10115",
- "region": "Berlin",
- "depositAmountCents": 150000
}{- "id": "vWRaPWn3iIDr8iBpdAHpW",
- "createdAt": "2025-10-23T10:00:00+02:00",
- "updatedAt": "2025-10-23T14:30:00+02:00",
- "version": "3",
- "iban": "DE89370400440532013000",
- "type": "INDIVIDUAL",
- "givenReference": "M03879.Obj0842",
- "sourceId": "pm-2024-unit-789",
- "streetName": "Hauptstraße",
- "streetNumber": "123",
- "postalCode": "10115",
- "region": "Berlin",
- "countryCode": "DE",
- "depositAmountCents": 150000,
- "rentalContractStartDate": "2025-01-01",
- "notes": "Tenant requested deposit split over two months",
- "payoutNote": "Deducted EUR 200 for cleaning",
- "moveOutDate": "2025-08-31",
- "propertyOwnerId": "vWRaPWn3iIDr8iBpdAHpW",
- "status": "COMPLETE",
- "rentalContractVersion": "2",
- "rentalContractUpdatedAt": "2025-10-23T14:30:00+02:00",
- "tenants": [
- {
- "firstName": "Max",
- "lastName": "Mustermann",
- "dateOfBirth": "1990-05-15",
- "version": "1"
}
]
}An immediate GET of the virtual deposit account can still return the pre-payout status. This operation converges later than the other writes, because the read model updates when the outgoing transfer is submitted to the bank rather than on this request. The stale window is observable on a partially funded account. On a fully funded account the recomputed status is the same value. See the Consistency section in the API description.
| depositAccountId required | string Example: uYfXVMXfUrTkv2vT4xZel The unique identifier of the deposit account |
| virtualDepositAccountId required | string Example: vKo8sCA4VWbTNk8msiqPA The unique identifier of the virtual deposit account |
| counterpartyName required | string <= 70 characters Name of the payout recipient. |
| counterpartyIban required | string^[A-Z]{2}[0-9]{2}[A-Z0-9]+$ IBAN of the payout recipient (SEPA). |
| remittanceInformation required | string <= 140 characters Remittance information for the transfer. |
| amountCents required | integer >= 1 Payout amount in cents. Must be positive and must not exceed the account's available balance. |
| idempotencyKey required | string <= 255 characters A client-chosen opaque string (up to 255 characters) that makes certain the underlying bank transfer is only ever sent once for this payout. |
{- "counterpartyName": "Max Mustermann",
- "counterpartyIban": "DE89370400440532013000",
- "remittanceInformation": "Kautionsrückzahlung Objekt 0842",
- "amountCents": 50000,
- "idempotencyKey": "payout-2025-10-23-vda-0842-01"
}{- "bankCreditTransferId": "3f8b2c1a-5d6e-4f7a-8b9c-0d1e2f3a4b5c",
- "idempotencyKey": "payout-2025-10-23-vda-0842-01",
- "status": "CREATED"
}This operation changes the account's status. An immediate GET can still return the pre-payout status. See the Consistency section in the API description.
The payout is a durable multi-step operation. Once the request has passed the checks above, it completes even if the connection drops or the service restarts before the response is sent. In that case you receive a transport error or a gateway error, and the payout is still requested, possibly a few minutes later. Treat such an error as an unknown outcome and retry the request with the same idempotency key. A 409 CONFLICT with errorCode PAYOUT_ALREADY_REQUESTED on the retry confirms the earlier request. A 202 means the retry performed it.
| depositAccountId required | string Example: uYfXVMXfUrTkv2vT4xZel The unique identifier of the deposit account |
| virtualDepositAccountId required | string Example: vKo8sCA4VWbTNk8msiqPA The unique identifier of the virtual deposit account |
| counterpartyName required | string [ 1 .. 70 ] characters Name of the payout recipient. |
| counterpartyIban required | string non-empty ^[A-Z]{2}[0-9]{2}[A-Z0-9]+$ IBAN of the payout recipient (SEPA). |
| remittanceInformation required | string [ 1 .. 140 ] characters Remittance information for the transfer. |
| idempotencyKey required | string [ 1 .. 255 ] characters ^[\w-]+$ A client-chosen opaque string (up to 255 characters) that makes certain the underlying bank transfer is only ever sent once for this payout. |
{- "counterpartyName": "Max Mustermann",
- "counterpartyIban": "DE89370400440532013000",
- "remittanceInformation": "Kautionsrückzahlung Objekt 0842",
- "idempotencyKey": "payout-2025-10-23-vda-0842-01"
}{- "virtualDepositAccountId": "vKo8sCA4VWbTNk8msiqPA",
- "fullyPaidOutAt": "2025-10-23T14:30:00+02:00",
- "bankCreditTransfer": {
- "bankCreditTransferId": "3f8b2c1a-5d6e-4f7a-8b9c-0d1e2f3a4b5c",
- "idempotencyKey": "payout-2025-10-23-vda-0842-01",
- "status": "CREATED"
}
}Retrieves the current balance of a virtual deposit account
This endpoint is strongly consistent. It reads the ledger directly, not the read model behind the other reads, so it reflects a write as soon as the write returns.
| depositAccountId required | string Example: uYfXVMXfUrTkv2vT4xZel The unique identifier of the deposit account |
| virtualDepositAccountId required | string Example: vKo8sCA4VWbTNk8msiqPA The unique identifier of the virtual deposit account |
| amountCents required | integer Current balance in cents |
| currency required | string Value: "EUR" Currency of the balance |
| updatedAt | string or null <date-time> Timestamp when the balance was last updated (ISO 8601 with timezone). Null if no transactions have occurred. |
{- "amountCents": 150000,
- "currency": "EUR",
- "updatedAt": "2025-10-23T14:30:00+02:00"
}Initiates the asynchronous generation of a tax certificate for a virtual deposit account and the requested tax year. Returns the created async job, which can be polled via the get async job endpoint and whose artifact can be downloaded once completed.
| depositAccountId required | string Example: uYfXVMXfUrTkv2vT4xZel The unique identifier of the deposit account |
| virtualDepositAccountId required | string Example: vKo8sCA4VWbTNk8msiqPA The unique identifier of the virtual deposit account |
| year required | integer The tax year for which the certificate should be generated. Must be between the year the virtual deposit account was opened and the current year. |
{- "year": 2024
}{- "id": "j8sCA4VWbTNk8msiqPAvK",
- "type": "TAX_CERTIFICATE",
- "referenceType": "VIRTUAL_DEPOSIT_ACCOUNT",
- "referenceId": "vKo8sCA4VWbTNk8msiqPA",
- "status": "PENDING",
- "createdAt": "2025-10-23T14:30:00+02:00",
- "completedAt": null,
- "errorCode": null,
- "version": "1"
}Initiates the asynchronous generation of an all-time bank statement (Kontoauszug) for a virtual deposit account. Returns the created async job, which can be polled via the get async job endpoint and whose artifact can be downloaded once completed.
| depositAccountId required | string Example: uYfXVMXfUrTkv2vT4xZel The unique identifier of the deposit account |
| virtualDepositAccountId required | string Example: vKo8sCA4VWbTNk8msiqPA The unique identifier of the virtual deposit account |
This operation takes no body parameters. The body is optional. When sent, it must be a JSON object. Unknown properties are ignored. A body that is not an object, such as an array or a scalar, is rejected.
{ }{- "id": "j8sCA4VWbTNk8msiqPAvK",
- "type": "STATEMENT",
- "referenceType": "VIRTUAL_DEPOSIT_ACCOUNT",
- "referenceId": "vKo8sCA4VWbTNk8msiqPA",
- "status": "PENDING",
- "createdAt": "2025-10-23T14:30:00+02:00",
- "completedAt": null,
- "errorCode": null,
- "version": "1"
}Retrieves the current state of an asynchronous job (e.g. tax certificate or bank statement generation) initiated for the authenticated manager.
| depositAccountId required | string Example: uYfXVMXfUrTkv2vT4xZel The unique identifier of the deposit account |
| virtualDepositAccountId required | string Example: vKo8sCA4VWbTNk8msiqPA The unique identifier of the virtual deposit account |
| jobId required | string Example: j8sCA4VWbTNk8msiqPAvK The unique identifier of the async job |
| id required | string |
| type required | string Enum: "TAX_CERTIFICATE" "STATEMENT" |
| referenceType required | string Value: "VIRTUAL_DEPOSIT_ACCOUNT" |
| referenceId required | string |
| status required | string Enum: "PENDING" "PROCESSING" "COMPLETED" "FAILED" |
| createdAt required | string <date-time> |
| completedAt required | string or null <date-time> |
| errorCode required | string or null |
| version required | string^[0-9]+$ |
{- "id": "j8sCA4VWbTNk8msiqPAvK",
- "type": "TAX_CERTIFICATE",
- "referenceType": "VIRTUAL_DEPOSIT_ACCOUNT",
- "referenceId": "vKo8sCA4VWbTNk8msiqPA",
- "status": "COMPLETED",
- "createdAt": "2025-10-23T14:30:00+02:00",
- "completedAt": "2025-10-23T14:31:00+02:00",
- "errorCode": null,
- "version": "3"
}Mints a fresh short-lived presigned HTTP-GET URL (TTL 7 days) for the completed job's artifact in partner-facing object storage; returns a new URL on every call.
| depositAccountId required | string Example: uYfXVMXfUrTkv2vT4xZel The unique identifier of the deposit account |
| virtualDepositAccountId required | string Example: vKo8sCA4VWbTNk8msiqPA The unique identifier of the virtual deposit account |
| jobId required | string Example: j8sCA4VWbTNk8msiqPAvK The unique identifier of the async job |
| jobId required | string |
| fileUrl required | string <uri> |
| expiresAt required | string <date-time> |
{- "jobId": "iDVh8yNUQ8y2hh1jkXTbi",
- "expiresAt": "2026-06-19T15:02:31.018Z"
}Retrieves all property owners with pagination support
This list serves a background-rebuilt read model. A freshly created property owner can be missing and a freshly updated one can show its previous field values. See the Consistency section in the API description.
| offset | integer >= 0 Default: 0 Example: offset=15 Number of items to skip before returning results |
| limit | integer [ 1 .. 100 ] Default: 15 Example: limit=15 Maximum number of items to return |
| offset required | integer >= 0 Number of items skipped before these results |
| limit required | integer [ 1 .. 100 ] Maximum number of items returned in this response |
| totalItems required | integer >= 0 Total number of items available |
required | Array of any (PropertyOwner) List of property owners for the current page |
{- "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",
- "version": "3",
- "type": "INDIVIDUAL",
- "firstName": "Anna",
- "lastName": "Müller",
- "streetName": "Hauptstraße",
- "streetNumber": "123",
- "postalCode": "10115",
- "region": "Berlin",
- "country": "DE",
- "emailAddress": "anna.mueller@example.com",
- "phoneNumber": "+49301234567",
- "taxIdNumber": "12345678901",
- "dateOfBirth": "1980-05-12",
- "hasCoowner": false,
- "coownerFirstName": null,
- "coownerLastName": null,
- "coownerDateOfBirth": null,
- "coownerTaxIdNumber": null
}, - {
- "id": "moTEwlVvx2N7U7Eo9Kl6n",
- "createdAt": "2025-09-20T14:15:00+02:00",
- "updatedAt": "2025-10-22T16:45:00+02:00",
- "version": "1",
- "type": "COMPANY",
- "firstName": "Max",
- "lastName": "Schmidt",
- "streetName": "Hauptstraße",
- "streetNumber": "123",
- "postalCode": "10115",
- "region": "Berlin",
- "country": "DE",
- "emailAddress": null,
- "phoneNumber": null,
- "taxIdNumber": "12345678901",
- "companyName": "Müller Immobilien GmbH"
}
]
}Creates a property owner scoped to the authenticated manager
The response body carries the created property owner and its version. An immediate GET of it can return 404 and an immediate list can omit it. See the Consistency section in the API description.
| id required | string Unique identifier for the entity |
| createdAt required | string <date-time> Timestamp when the entity was created (ISO 8601 with timezone) |
| updatedAt | string <date-time> Timestamp when the entity was last updated (ISO 8601 with timezone) |
| version required | string^[0-9]+$ Opaque optimistic-concurrency token for the entity. Round-trip this value unchanged on mutating requests (PATCH, DELETE) to detect stale writes. Read endpoints lag writes by a short window, so after a write of your own take this token from that write's response body rather than from a |
| type required | string Type of property owner |
| firstName required | string Individual: the owner's first name. Company: the contact person's first name. |
| lastName required | string Individual: the owner's last name. Company: the contact person's last name. |
| streetName required | string |
| streetNumber required | string |
| postalCode required | string |
| region required | string |
| country required | string |
| emailAddress | string or null <email> |
| phoneNumber | string or null |
| taxIdNumber | string or null German tax identification number |
| dateOfBirth | string or null <date> |
| hasCoowner required | boolean |
| coownerFirstName | string or null |
| coownerLastName | string or null |
| coownerDateOfBirth | string or null <date> |
| coownerTaxIdNumber | string or null |
{- "type": "INDIVIDUAL",
- "firstName": "Max",
- "lastName": "Mustermann",
- "streetName": "Hauptstraße",
- "streetNumber": "123",
- "postalCode": "10115",
- "region": "Berlin",
- "country": "DE",
- "emailAddress": "max.mustermann@example.com",
- "phoneNumber": "+49301234567",
- "taxIdNumber": "12345678901",
- "dateOfBirth": "1980-05-12",
- "hasCoowner": true,
- "coownerFirstName": "Erika",
- "coownerLastName": "Mustermann",
- "coownerDateOfBirth": "1982-07-01",
- "coownerTaxIdNumber": "98765432109"
}{- "id": "vWRaPWn3iIDr8iBpdAHpW",
- "createdAt": "2025-10-23T10:00:00+02:00",
- "updatedAt": "2025-10-23T14:30:00+02:00",
- "version": "3",
- "type": "INDIVIDUAL",
- "firstName": "Anna",
- "lastName": "Müller",
- "streetName": "Hauptstraße",
- "streetNumber": "123",
- "postalCode": "10115",
- "region": "Berlin",
- "country": "DE",
- "emailAddress": "user@example.com",
- "phoneNumber": "string",
- "taxIdNumber": "string",
- "dateOfBirth": "2019-08-24",
- "hasCoowner": true,
- "coownerFirstName": "string",
- "coownerLastName": "string",
- "coownerDateOfBirth": "2019-08-24",
- "coownerTaxIdNumber": "string"
}Retrieves a single property owner by its unique identifier
This endpoint serves a background-rebuilt read model. Right after a create it can return 404, and right after an update it can return the pre-update fields and the pre-update version. See the Consistency section in the API description.
| propertyOwnerId required | string Example: vWRaPWn3iIDr8iBpdAHpW The unique identifier of the property owner |
| id required | string Unique identifier for the entity |
| createdAt required | string <date-time> Timestamp when the entity was created (ISO 8601 with timezone) |
| updatedAt | string <date-time> Timestamp when the entity was last updated (ISO 8601 with timezone) |
| version required | string^[0-9]+$ Opaque optimistic-concurrency token for the entity. Round-trip this value unchanged on mutating requests (PATCH, DELETE) to detect stale writes. Read endpoints lag writes by a short window, so after a write of your own take this token from that write's response body rather than from a |
| type required | string Type of property owner |
| firstName required | string Individual: the owner's first name. Company: the contact person's first name. |
| lastName required | string Individual: the owner's last name. Company: the contact person's last name. |
| streetName required | string |
| streetNumber required | string |
| postalCode required | string |
| region required | string |
| country required | string |
| emailAddress | string or null <email> |
| phoneNumber | string or null |
| taxIdNumber | string or null German tax identification number |
| dateOfBirth | string or null <date> |
| hasCoowner required | boolean |
| coownerFirstName | string or null |
| coownerLastName | string or null |
| coownerDateOfBirth | string or null <date> |
| coownerTaxIdNumber | string or null |
{- "id": "vWRaPWn3iIDr8iBpdAHpW",
- "createdAt": "2025-09-15T09:00:00+02:00",
- "updatedAt": "2025-10-20T11:30:00+02:00",
- "version": "3",
- "type": "INDIVIDUAL",
- "firstName": "Anna",
- "lastName": "Müller",
- "streetName": "Hauptstraße",
- "streetNumber": "123",
- "postalCode": "10115",
- "region": "Berlin",
- "country": "DE",
- "emailAddress": "anna.mueller@example.com",
- "phoneNumber": "+49301234567",
- "taxIdNumber": "12345678901",
- "dateOfBirth": "1980-05-12",
- "hasCoowner": false,
- "coownerFirstName": null,
- "coownerLastName": null,
- "coownerDateOfBirth": null,
- "coownerTaxIdNumber": null
}Updates a property owner scoped to the authenticated manager. Only the fields present in the request body are changed; omitted fields are left unchanged and an explicit null clears a nullable field. The supplied version must match the property owner's current version.
This operation increments the version and returns the new one in the response body. Use that value for your next write. An immediate GET can return every mutable field at its pre-update value together with the pre-update version, and sending that version back produces 409 CONFLICT / PROPERTY_OWNER_VERSION_CONFLICT with no concurrent writer involved. See the Consistency section in the API description.
| propertyOwnerId required | string Example: vWRaPWn3iIDr8iBpdAHpW The unique identifier of the property owner |
| id required | string Unique identifier for the entity |
| createdAt required | string <date-time> Timestamp when the entity was created (ISO 8601 with timezone) |
| updatedAt | string <date-time> Timestamp when the entity was last updated (ISO 8601 with timezone) |
| version required | string^[0-9]+$ Opaque optimistic-concurrency token for the entity. Round-trip this value unchanged on mutating requests (PATCH, DELETE) to detect stale writes. Read endpoints lag writes by a short window, so after a write of your own take this token from that write's response body rather than from a |
| type required | string Type of property owner |
| firstName required | string Individual: the owner's first name. Company: the contact person's first name. |
| lastName required | string Individual: the owner's last name. Company: the contact person's last name. |
| streetName required | string |
| streetNumber required | string |
| postalCode required | string |
| region required | string |
| country required | string |
| emailAddress | string or null <email> |
| phoneNumber | string or null |
| taxIdNumber | string or null German tax identification number |
| dateOfBirth | string or null <date> |
| hasCoowner required | boolean |
| coownerFirstName | string or null |
| coownerLastName | string or null |
| coownerDateOfBirth | string or null <date> |
| coownerTaxIdNumber | string or null |
{- "version": "3",
- "type": "INDIVIDUAL",
- "firstName": "Max",
- "lastName": "Mustermann",
- "streetName": "Hauptstraße",
- "streetNumber": "123",
- "postalCode": "10115",
- "region": "Berlin",
- "country": "DE",
- "emailAddress": "max.mustermann@example.com",
- "phoneNumber": "+49301234567",
- "taxIdNumber": "12345678901",
- "dateOfBirth": "1980-05-12",
- "hasCoowner": true,
- "coownerFirstName": "Erika",
- "coownerLastName": "Mustermann",
- "coownerDateOfBirth": "1982-07-01",
- "coownerTaxIdNumber": "98765432109"
}{- "id": "vWRaPWn3iIDr8iBpdAHpW",
- "createdAt": "2025-10-23T10:00:00+02:00",
- "updatedAt": "2025-10-23T14:30:00+02:00",
- "version": "3",
- "type": "INDIVIDUAL",
- "firstName": "Anna",
- "lastName": "Müller",
- "streetName": "Hauptstraße",
- "streetNumber": "123",
- "postalCode": "10115",
- "region": "Berlin",
- "country": "DE",
- "emailAddress": "user@example.com",
- "phoneNumber": "string",
- "taxIdNumber": "string",
- "dateOfBirth": "2019-08-24",
- "hasCoowner": true,
- "coownerFirstName": "string",
- "coownerLastName": "string",
- "coownerDateOfBirth": "2019-08-24",
- "coownerTaxIdNumber": "string"
}

Every 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.
Header format: v1,<base64-encoded-signature>
Verification examples:
import crypto from 'node:crypto';
function verifySignature(secret: string, body: string, header: string): boolean {
const signature = crypto.createHmac('sha256', secret).update(body).digest('base64');
const expected = `v1,${signature}`;
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(header));
}
import hmac
import hashlib
import base64
def verify_signature(secret: str, body: bytes, header: str) -> bool:
signature = base64.b64encode(
hmac.new(secret.encode(), body, hashlib.sha256).digest()
).decode()
expected = f"v1,{signature}"
return hmac.compare_digest(expected, header)
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
)
func VerifySignature(secret, body, header string) bool {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(body))
expected := fmt.Sprintf("v1,%s", base64.StdEncoding.EncodeToString(mac.Sum(nil)))
return hmac.Equal([]byte(expected), []byte(header))
}
using System.Security.Cryptography;
using System.Text;
public static bool VerifySignature(string secret, string body, string header)
{
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(body));
var expected = $"v1,{Convert.ToBase64String(hash)}";
return CryptographicOperations.FixedTimeEquals(
Encoding.UTF8.GetBytes(expected),
Encoding.UTF8.GetBytes(header)
);
}
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
import java.util.Base64;
public static boolean verifySignature(String secret, String body, String header) throws Exception {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
String signature = Base64.getEncoder().encodeToString(mac.doFinal(body.getBytes("UTF-8")));
String expected = "v1," + signature;
return MessageDigest.isEqual(expected.getBytes("UTF-8"), header.getBytes("UTF-8"));
}
require 'openssl'
require 'base64'
def verify_signature(secret, body, header)
signature = Base64.strict_encode64(
OpenSSL::HMAC.digest('sha256', secret, body)
)
expected = "v1,#{signature}"
Rack::Utils.secure_compare(expected, header)
end
function verifySignature(string $secret, string $body, string $header): bool {
$signature = base64_encode(hash_hmac('sha256', $body, $secret, true));
$expected = "v1,{$signature}";
return hash_equals($expected, $header);
}
Always use a constant-time comparison function to prevent timing attacks.
POST requests with Content-Type: application/json2xx status code to acknowledge receiptAll events share a common envelope:
{
"type": "<EVENT_TYPE>",
"payload": { ... }
}
The type field identifies the event. The payload shape depends on the event type.
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.
| X-Getmomo-Signature required | string Example: v1,K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols= HMAC-SHA256 signature of the request body. Format: |
| type required | string Value: "TEST" Event type identifier |
required | object (WebhookTestPayload) |
{- "type": "TEST",
- "payload": {
- "triggered_at": "2026-03-26T12:00:00.000Z"
}
}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.
| X-Getmomo-Signature required | string Example: v1,K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols= HMAC-SHA256 signature of the request body. Format: |
| type required | string Value: "VIRTUAL_DEPOSIT_ACCOUNT_BALANCE_UPDATED" Event type identifier |
required | object (WebhookVirtualDepositAccountBalanceUpdatedPayload) |
{- "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"
}
}Sent whenever an asynchronous job started via the Public API (tax certificate or statement generation) reaches a terminal status (COMPLETED or FAILED). Use this instead of polling the job status endpoint. 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.
| X-Getmomo-Signature required | string Example: v1,K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols= HMAC-SHA256 signature of the request body. Format: |
| type required | string Value: "PUBLIC_API_ASYNC_JOB_STATUS_CHANGED" Event type identifier |
required | object (WebhookPublicApiAsyncJobStatusChangedPayload) |
{- "type": "PUBLIC_API_ASYNC_JOB_STATUS_CHANGED",
- "payload": {
- "jobId": "job-abc123",
- "jobType": "TAX_CERTIFICATE",
- "referenceType": "VIRTUAL_DEPOSIT_ACCOUNT",
- "referenceId": "virtual-deposit-account-def456",
- "status": "COMPLETED",
- "completedAt": "2026-04-07T12:00:00.000Z",
- "errorCode": null
}
}