Transaction
A Transaction is money moving on a payment rail, such as a charge, a payout, or a transfer, reconciled to Entries.
Properties
| Property | Type | Required | Description |
|---|---|---|---|
kind | string | required | One of charge, refund, payout, or transfer. |
amount | money | required | The amount moved. |
receipt | File | The receipt matched to a card Transaction. | |
settledAt | datetime | When the money became available in a cash Account. |
Object
{
"$id": "https: //api.sb/ tutorloop.com/ transactions/ transaction_1",
"$type": "Transaction",
"kind": "charge",
"amount": {
"amount": 60,
"currency": "USD"
},
"receipt": "file_1",
"settledAt": "2026-10-22T12: 00: 00Z"
}Relationships
- A Transaction reconciles many Entries: the ledger Entries the Transaction settles, matched during reconciliation.
reconciles, inversereconciledBy.
Verbs
getReturns one Transaction by id.GET /{namespace}/transactions/{id}listReturns Transactions, newest first, one page at a time.GET /{namespace}/transactionsattachAttach matches a receipt File to a card Transaction, or flags the Transaction when no receipt arrives in time.POST /{namespace}/transactions/{transaction}/attachcategorizeCategorize codes a Transaction to an account in the chart by the Startup’s Policy and flags a low-confidence code for review.POST /{namespace}/transactions/{transaction}/categorizereconcileReconcile matches a Transaction on a payment rail to the ledger Entries it settles.POST /{namespace}/transactions/{transaction}/reconcile
A Transaction is kept forever and never edited: it has no update or delete.
Events
Events no Verb emits. Each Verb’s Event is in the Verbs table above; every Event is delivered in the same shape.
Transaction.failed
The rail refused a charge or payout Transaction after it was sent. Raised by the rail.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | required | Transaction.failed. |
at | datetime | required | When it happened. |
seq | integer | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. | |
data | json | required | The Thing as the Action left it. |
data.transaction | Transaction | required | The Transaction as the change left it. |
data.transaction.kind | string | required | One of charge, refund, payout, or transfer. |
data.transaction.amount | money | required | The amount moved. |
data.transaction.receipt | File | The receipt matched to a card Transaction. | |
data.transaction.settledAt | datetime | When the money became available in a cash Account. | |
data.reason | text | required | Why the rail refused it, in the rail’s words. |
{
"$id": "https: //api.sb/ tutorloop.com/ events/ event_1",
"$type": "Event",
"name": "Transaction.failed",
"at": "2026-10-22T12: 00: 00Z",
"data": {
"transaction": {
"$id": "https: //api.sb/ tutorloop.com/ transactions/ transaction_1",
"$type": "Transaction",
"kind": "charge",
"amount": {
"amount": 60,
"currency": "USD"
},
"receipt": "file_1",
"settledAt": "2026-10-22T12: 00: 00Z"
},
"reason": "The bank declined the transfer."
},
"seq": 1
}Transaction.settled
The money in a Transaction became available in a cash Account. Raised by the rail.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | required | Transaction.settled. |
at | datetime | required | When it happened. |
seq | integer | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. | |
data | json | required | The Thing as the Action left it. |
data.transaction | Transaction | required | The Transaction as the change left it. |
data.transaction.kind | string | required | One of charge, refund, payout, or transfer. |
data.transaction.amount | money | required | The amount moved. |
data.transaction.receipt | File | The receipt matched to a card Transaction. | |
data.transaction.settledAt | datetime | When the money became available in a cash Account. | |
data.account | Account | required | The cash Account the money is in. |
data.availableAt | datetime | required | When the money became available. |
{
"$id": "https: //api.sb/ tutorloop.com/ events/ event_1",
"$type": "Event",
"name": "Transaction.settled",
"at": "2026-10-22T12: 00: 00Z",
"data": {
"transaction": {
"$id": "https: //api.sb/ tutorloop.com/ transactions/ transaction_1",
"$type": "Transaction",
"kind": "charge",
"amount": {
"amount": 60,
"currency": "USD"
},
"receipt": "file_1",
"settledAt": "2026-10-22T12: 00: 00Z"
},
"account": {
"$id": "https: //api.sb/ tutorloop.com/ accounts/ account_1",
"$type": "Account",
"class": "cash"
},
"availableAt": "2026-10-22T12: 00: 00Z"
},
"seq": 1
}Permissions
Which Access level may call each Verb. One-way Verbs wait their delay window.
| Operation | owner | admin | member | viewer |
|---|---|---|---|---|
Transaction.get | Yes | Yes | Yes | Yes |
Transaction.list | Yes | Yes | Yes | Yes |
Transaction.attach | Yes | Yes | Yes | No |
Transaction.categorize | Yes | Yes | Yes | No |
Transaction.reconcile | Yes | Yes | Yes | No |
Stripe
PaymentIntent (payment_intent), for a Transaction whose kind is charge. The source of truth is Stripe: db.sb mirrors it, written only from Stripe’s webhooks.
| Property | Stripe field | Source of truth |
|---|---|---|
amount | amount | Stripe |
Payout (payout), for a Transaction whose kind is payout. The source of truth is Stripe: db.sb mirrors it, written only from Stripe’s webhooks.
| Property | Stripe field | Source of truth |
|---|---|---|
amount | amount | Stripe |
Refund (refund), for a Transaction whose kind is refund. The source of truth is Stripe: db.sb mirrors it, written only from Stripe’s webhooks.
| Property | Stripe field | Source of truth |
|---|---|---|
amount | amount | Stripe |
Call it
Reconcile the latest transaction.Example
A $49 Stripe charge is a Transaction. The monthly close reconciles it to two Entries.