Regular Transactions Schema
Field reference for user-scoped regular transaction series detect and result messages on Kafka.
Overview
Regular transaction series detection is user-scoped: every detect and result message includes a userId, and result egress is always shaped as { userId, accounts[] }. A user may have multiple accounts (for example, a current account and a credit card).
To request detection, publish a message to the regular-transactions detect topic. A user-scoped result is then published to the regular-transactions result topic.
Detect messages may contain one account or several accounts for the same user. Moneyhub configures how daily batch detection is grouped for your environment; see List of configurable features.
This mirrors the affordability interface: one userId in, one user-scoped message out per detect message processed.
Request message
The Kafka message value must be a JSON object:
| Field | Type | Optional | Description |
|---|---|---|---|
| userId | String (max 36) | No | User identifier whose accounts are being processed. |
| accounts | Array<Object> | No | Accounts to process. At least one entry is required. |
Each element of accounts[]:
| Field | Type | Optional | Description |
|---|---|---|---|
| accountId | String (max 36) | No | Account identifier to detect series for. |
| mode | String (max 11) | Yes | Detection mode: full (default) or incremental. |
| updatedAt | String | Yes | ISO 8601 timestamp. Required when mode is incremental; ignored for full. |
In full mode, detection uses the configured retention window of transaction history. In incremental mode, it uses transactions from updatedAt onwards and merges with existing predictions.
The message key should be a unique identifier (UUID recommended). It is copied to the corresponding result message.
Example (detect message — single account)
{
"userId": "550e8400-e29b-41d4-a716-446655440000",
"accounts": [
{
"accountId": "090ea264-eb48-494c-9d59-1b10b322c3e1",
"mode": "full"
}
]
}Example (detect message — multiple accounts)
{
"userId": "550e8400-e29b-41d4-a716-446655440000",
"accounts": [
{
"accountId": "090ea264-eb48-494c-9d59-1b10b322c3e1",
"mode": "full"
},
{
"accountId": "de4be182-efb4-4aad-b221-fa29631e6653",
"mode": "incremental",
"updatedAt": "2026-06-01T12:00:00.000Z"
}
]
}Result topic
Detection results are published to the regular-transactions result topic. Failed messages are sent to the regular-transactions dead-letter topic; see Errors for the general dead-letter envelope shape.
Result message envelope
The Kafka message value is a JSON object:
| Field | Type | Optional | Description |
|---|---|---|---|
| userId | String (max 36) | No | User identifier that was requested for the detection run. |
| accounts | Array<Object> | No | Detection results per account (schema below). One entry per account processed. |
The message key is copied from the triggering detect message when present; otherwise a new UUID is generated.
Account result (accounts[])
accounts[])| Field | Type | Optional | Description |
|---|---|---|---|
| accountId | String (max 36) | No | Account identifier for which series were computed. |
| predictions | Array<Object> | No | Array of regular transaction series objects (schema below). May be empty. |
Series object (predictions[])
predictions[])| Field | Type | Optional | Description |
|---|---|---|---|
| seriesId | String (max 36) | No | The ID of the regular transaction series. UUID format. |
| accountId | String (max 36) | No | The ID of the account the transactions belong to. Matches the parent accounts[].accountId. |
| userId | String (max 36) | No | The ID of the user the transactions belong to. Matches the envelope userId. |
| type | String (max 7) | No | Whether the series contains income or payment transactions (income or payment). |
| subtype | String (max 21) | Yes | Subtype: directDebit, standingOrder, frequentVisit, committedCardPayment, or other. |
| frequency | String (max 11) | No | Frequency: yearly, quarterly, monthly, fortnightly, or weekly. |
| description | String (max 256) | No | The full description of the latest transaction in the series. Same limit as enriched transaction description. |
| cleanedDescription | String (max 256) | No | The cleaned description of the latest transaction in the series. |
| numTxMatchedInSeries | Integer | No | The number of transactions contained in the series. |
| gapLengthInFreqUnits | Integer | No | If the series contains a gap, the number of whole frequency units that are missing. |
| dateAnomaliesCount | Integer | No | The number of date anomalies detected in the series. |
| numReturnedTxs | Integer | No | The number of returned transactions (reversed or declined) contained in the series. |
| lastDate | String (max 10) | No | The date of the latest transaction in the series (yyyy-MM-dd). |
| predictedDate | String (max 10) | No | The predicted date of the next transaction in the series (yyyy-MM-dd). |
| predictedDateEarliest | String (max 10) | Yes | The earliest predicted date at which the next transaction could occur (null if not set). |
| predictedDateLatest | String (max 10) | Yes | The latest predicted date at which the next transaction could occur (null if not set). |
| predictedTxLateOrNotDetected | Boolean | Yes | Whether the next predicted transaction is overdue or not detected. May be omitted if not set. |
| predictedAmount | Number | No | The predicted amount of the next transaction (as emitted by detection; currency base units where applicable). |
| predictedAmountLower | Number | Yes | Lower bound of the predicted amount. |
| predictedAmountUpper | Number | Yes | Upper bound of the predicted amount. |
| currency | String (max 3) | Yes | ISO 4217 currency code. Same limit as enriched transaction currency. |
| counterpartyId | String (max 36) | Yes | L3 counterparty identifier from the first matched transaction that has counterparty enrichment. UUID format. |
| predictedCategoryId | String (max 3) | No | The ID of the predicted category. Same limit as enriched transaction l2CategoryId. |
| l3CounterpartyCategory | String (max 32) | Yes | The counterparty analysis category identifier. Same limit as counterparty l3CounterpartyCategory. May be null. |
| transactions | Array<Object> | No | Matched historical transactions in the series (schema below). |
Transaction object (transactions[])
transactions[])| Field | Type | Optional | Description |
|---|---|---|---|
| uid | String (max 36) | No | Transaction identifier. |
| date | String (max 10) | No | Transaction date (yyyy-MM-dd). |
| description | String (max 256) | No | Transaction description. |
| amount | Number | No | Transaction amount. |
| categoryId | String (max 3) | No | L2 category identifier. |
| cleanedDescription | String (max 256) | No | Cleaned description. |
| txCode | String (max 64) | Yes | Provider transaction type code. |
| cardPresent | Boolean | Yes | Whether the transaction was card-present. |
| l3CounterpartyCategory | String (max 32) | Yes | Counterparty analysis category identifier. May be null when not available. |
Example (result message body)
{
"userId": "550e8400-e29b-41d4-a716-446655440000",
"accounts": [
{
"accountId": "090ea264-eb48-494c-9d59-1b10b322c3e1",
"predictions": [
{
"seriesId": "45f004dc-254f-5d09-b07f-8d4de4487781",
"accountId": "090ea264-eb48-494c-9d59-1b10b322c3e1",
"userId": "550e8400-e29b-41d4-a716-446655440000",
"type": "payment",
"subtype": "frequentVisit",
"frequency": "quarterly",
"description": "Dentist Checkup",
"cleanedDescription": "Dentist Checkup",
"numTxMatchedInSeries": 4,
"gapLengthInFreqUnits": 0,
"dateAnomaliesCount": 0,
"numReturnedTxs": 0,
"lastDate": "2026-01-20",
"predictedDate": "2026-04-20",
"predictedDateEarliest": "2026-04-20",
"predictedDateLatest": "2026-04-21",
"predictedTxLateOrNotDetected": false,
"predictedAmount": -65,
"predictedAmountLower": -65,
"predictedAmountUpper": -65,
"currency": "GBP",
"counterpartyId": "203d5a9a-d4dd-5ce5-ab60-60f740336dea",
"predictedCategoryId": "11",
"l3CounterpartyCategory": null,
"transactions": [
{
"uid": "TXN-090ea264-775",
"date": "2026-01-20",
"description": "Dentist Checkup",
"amount": -65,
"categoryId": "11",
"cleanedDescription": "Dentist Checkup",
"txCode": null,
"cardPresent": false,
"l3CounterpartyCategory": null
},
{
"uid": "TXN-090ea264-774",
"date": "2025-10-20",
"description": "Dentist Checkup",
"amount": -65,
"categoryId": "11",
"cleanedDescription": "Dentist Checkup",
"txCode": null,
"cardPresent": false,
"l3CounterpartyCategory": null
}
]
}
]
},
{
"accountId": "de4be182-efb4-4aad-b221-fa29631e6653",
"predictions": []
}
]
}Updated 3 days ago
