curl -s \
"https://engine.example.com/v1/holders/alpha/movements?limit=100" \
-H "Authorization: Bearer $TOKEN"
# Send each page's next back as after, until null.// A client from OpenAPI Generator: see Build a client.
import {
Configuration,
ProblemFromJSON,
ReportsApi,
ResponseError,
} from "./nodeasset-client";
const api = new ReportsApi(new Configuration({
basePath: "https://engine.example.com",
accessToken: process.env.TOKEN,
}));
try {
// Send each page's next back as after, until null.
let after: string | undefined;
do {
const page = await api.listHolderMovements({ holderId: "alpha", limit: 100, after });
for (const movement of page.value ?? []) {
console.log(movement);
}
after = page.next ?? undefined;
} while (after);
} catch (e) {
if (!(e instanceof ResponseError)) throw e;
// A refusal is a problem; its type ends in the slug.
const problem = ProblemFromJSON(await e.response.json());
const slug = problem.type.split(":").pop();
console.error(e.response.status, slug, problem.detail);
}
# A client from OpenAPI Generator: see Build a client.
import os
import sys
import nodeasset_client
config = nodeasset_client.Configuration(
host="https://engine.example.com",
access_token=os.environ["TOKEN"],
)
with nodeasset_client.ApiClient(config) as client:
api = nodeasset_client.ReportsApi(client)
try:
# Send each page's next back as after, until null.
after = None
while True:
page = api.list_holder_movements(holder_id="alpha", limit=100, after=after)
for movement in page.value or []:
print(movement)
after = page.next
if after is None:
break
except nodeasset_client.ApiException as e:
# A refusal is a problem; its type ends in the slug.
problem = nodeasset_client.Problem.from_json(e.body)
slug = problem.type.rsplit(":", 1)[-1]
print(e.status, slug, problem.detail, file=sys.stderr)
// A client from OpenAPI Generator: see Build a client.
import nodeasset.client.ApiClient;
import nodeasset.client.ApiException;
import nodeasset.client.api.ReportsApi;
import nodeasset.client.model.Problem;
public class ListHolderMovements {
public static void main(String[] args) throws Exception {
ApiClient client = new ApiClient();
client.updateBaseUri("https://engine.example.com");
client.setRequestInterceptor(builder ->
builder.header("Authorization", "Bearer " + System.getenv("TOKEN")));
ReportsApi api = new ReportsApi(client);
try {
// Send each page's next back as after, until null.
String after = null;
do {
var request = ReportsApi.APIListHolderMovementsRequest.newBuilder()
.holderId("alpha")
.limit(100)
.after(after)
.build();
var page = api.listHolderMovements(request);
for (var movement : page.getValue()) {
System.out.println(movement);
}
after = page.getNext();
} while (after != null);
} catch (ApiException e) {
// A refusal is a problem; its type ends in the slug.
Problem problem = client.getObjectMapper()
.readValue(e.getResponseBody(), Problem.class);
String type = problem.getType();
String slug = type.substring(type.lastIndexOf(':') + 1);
System.err.println(e.getCode() + " " + slug + " " + problem.getDetail());
}
}
}
{
"offset": 669,
"ledgerTime": "2026-10-03T13:26:05.515351Z",
"now": "2026-10-03T13:26:06.127351902Z",
"value": [
{
"instrumentId": "FUND",
"account": {
"owner": "alpha::12207ae69b2ef2f1249abd41923a06ee30bffa9298a17b0a875355c441bf32045d73",
"provider": null,
"id": ""
},
"holderId": "alpha",
"kind": "subscription",
"units": 250,
"balanceAfter": 5250,
"at": "2026-10-03T13:22:18.611274Z",
"offset": 588,
"updateId": "1220d7b0e4a6f81b9c3d2e5f4a7b6c9d8e1f0a3b2c5d4e7f6a9b8c1d0e3f2a5b4c7d",
"counterparty": null,
"counterpartyHolderId": null,
"price": 1.003,
"amount": 250.75,
"amountInstrumentId": "TD",
"references": {
"settlementId": null,
"subscriptionId": "lot-alpha-0003",
"redemptionId": null,
"dealingCycleId": null,
"distributionId": null,
"operationId": null,
"reference": "lot-alpha-0003"
}
},
{
"instrumentId": "FUND",
"account": {
"owner": "alpha::12207ae69b2ef2f1249abd41923a06ee30bffa9298a17b0a875355c441bf32045d73",
"provider": null,
"id": ""
},
"holderId": "alpha",
"kind": "distribution",
"units": 16.92,
"balanceAfter": 5266.92,
"at": "2026-10-03T13:24:02.004561Z",
"offset": 617,
"updateId": "1220a5f3c7e9b1d3f5a7c9e1b3d5f7a9c1e3b5d7f9a1c3e5b7d9f1a3c5e7b9d1f3",
"counterparty": {
"owner": "issuer::12207ae69b2ef2f1249abd41923a06ee30bffa9298a17b0a875355c441bf32045d73",
"provider": null,
"id": ""
},
"counterpartyHolderId": null,
"price": null,
"amount": null,
"amountInstrumentId": null,
"references": {
"settlementId": null,
"subscriptionId": null,
"redemptionId": null,
"dealingCycleId": null,
"distributionId": "dist-FUND-2026-09",
"operationId": null,
"reference": null
}
}
],
"next": null
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}List a holder's movements
Lists each change of the holder’s units and its predecessors’, oldest first, with its kind, the balance after it and its references. An investor reads its own holder only.
curl -s \
"https://engine.example.com/v1/holders/alpha/movements?limit=100" \
-H "Authorization: Bearer $TOKEN"
# Send each page's next back as after, until null.// A client from OpenAPI Generator: see Build a client.
import {
Configuration,
ProblemFromJSON,
ReportsApi,
ResponseError,
} from "./nodeasset-client";
const api = new ReportsApi(new Configuration({
basePath: "https://engine.example.com",
accessToken: process.env.TOKEN,
}));
try {
// Send each page's next back as after, until null.
let after: string | undefined;
do {
const page = await api.listHolderMovements({ holderId: "alpha", limit: 100, after });
for (const movement of page.value ?? []) {
console.log(movement);
}
after = page.next ?? undefined;
} while (after);
} catch (e) {
if (!(e instanceof ResponseError)) throw e;
// A refusal is a problem; its type ends in the slug.
const problem = ProblemFromJSON(await e.response.json());
const slug = problem.type.split(":").pop();
console.error(e.response.status, slug, problem.detail);
}
# A client from OpenAPI Generator: see Build a client.
import os
import sys
import nodeasset_client
config = nodeasset_client.Configuration(
host="https://engine.example.com",
access_token=os.environ["TOKEN"],
)
with nodeasset_client.ApiClient(config) as client:
api = nodeasset_client.ReportsApi(client)
try:
# Send each page's next back as after, until null.
after = None
while True:
page = api.list_holder_movements(holder_id="alpha", limit=100, after=after)
for movement in page.value or []:
print(movement)
after = page.next
if after is None:
break
except nodeasset_client.ApiException as e:
# A refusal is a problem; its type ends in the slug.
problem = nodeasset_client.Problem.from_json(e.body)
slug = problem.type.rsplit(":", 1)[-1]
print(e.status, slug, problem.detail, file=sys.stderr)
// A client from OpenAPI Generator: see Build a client.
import nodeasset.client.ApiClient;
import nodeasset.client.ApiException;
import nodeasset.client.api.ReportsApi;
import nodeasset.client.model.Problem;
public class ListHolderMovements {
public static void main(String[] args) throws Exception {
ApiClient client = new ApiClient();
client.updateBaseUri("https://engine.example.com");
client.setRequestInterceptor(builder ->
builder.header("Authorization", "Bearer " + System.getenv("TOKEN")));
ReportsApi api = new ReportsApi(client);
try {
// Send each page's next back as after, until null.
String after = null;
do {
var request = ReportsApi.APIListHolderMovementsRequest.newBuilder()
.holderId("alpha")
.limit(100)
.after(after)
.build();
var page = api.listHolderMovements(request);
for (var movement : page.getValue()) {
System.out.println(movement);
}
after = page.getNext();
} while (after != null);
} catch (ApiException e) {
// A refusal is a problem; its type ends in the slug.
Problem problem = client.getObjectMapper()
.readValue(e.getResponseBody(), Problem.class);
String type = problem.getType();
String slug = type.substring(type.lastIndexOf(':') + 1);
System.err.println(e.getCode() + " " + slug + " " + problem.getDetail());
}
}
}
{
"offset": 669,
"ledgerTime": "2026-10-03T13:26:05.515351Z",
"now": "2026-10-03T13:26:06.127351902Z",
"value": [
{
"instrumentId": "FUND",
"account": {
"owner": "alpha::12207ae69b2ef2f1249abd41923a06ee30bffa9298a17b0a875355c441bf32045d73",
"provider": null,
"id": ""
},
"holderId": "alpha",
"kind": "subscription",
"units": 250,
"balanceAfter": 5250,
"at": "2026-10-03T13:22:18.611274Z",
"offset": 588,
"updateId": "1220d7b0e4a6f81b9c3d2e5f4a7b6c9d8e1f0a3b2c5d4e7f6a9b8c1d0e3f2a5b4c7d",
"counterparty": null,
"counterpartyHolderId": null,
"price": 1.003,
"amount": 250.75,
"amountInstrumentId": "TD",
"references": {
"settlementId": null,
"subscriptionId": "lot-alpha-0003",
"redemptionId": null,
"dealingCycleId": null,
"distributionId": null,
"operationId": null,
"reference": "lot-alpha-0003"
}
},
{
"instrumentId": "FUND",
"account": {
"owner": "alpha::12207ae69b2ef2f1249abd41923a06ee30bffa9298a17b0a875355c441bf32045d73",
"provider": null,
"id": ""
},
"holderId": "alpha",
"kind": "distribution",
"units": 16.92,
"balanceAfter": 5266.92,
"at": "2026-10-03T13:24:02.004561Z",
"offset": 617,
"updateId": "1220a5f3c7e9b1d3f5a7c9e1b3d5f7a9c1e3b5d7f9a1c3e5b7d9f1a3c5e7b9d1f3",
"counterparty": {
"owner": "issuer::12207ae69b2ef2f1249abd41923a06ee30bffa9298a17b0a875355c441bf32045d73",
"provider": null,
"id": ""
},
"counterpartyHolderId": null,
"price": null,
"amount": null,
"amountInstrumentId": null,
"references": {
"settlementId": null,
"subscriptionId": null,
"redemptionId": null,
"dealingCycleId": null,
"distributionId": "dist-FUND-2026-09",
"operationId": null,
"reference": null
}
}
],
"next": null
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"requestId": "<string>",
"gate": "<string>",
"check": "<string>",
"recovery": "<string>",
"retryAfter": 123,
"retryable": true,
"packageName": "<string>",
"party": "<string>",
"contractId": "<string>",
"projectionOffset": 123,
"ledgerEnd": 123,
"code": 123,
"reason": "<string>",
"policyVersion": 123,
"errors": [
{
"pointer": "<string>",
"detail": "<string>"
}
]
}app, approver, auditor, investor, operator, risk. An investor reaches only its own holder’s records.Authorizations
A JWT from the deployment's identity provider, whose roles claim names the caller's roles and whose holder claim names an investor's holder.
Headers
A signed request's key id, as venue.api.signing.clients configures it for the bearer's subject.
Seconds since the epoch, within venue.api.signing.window of the engine's clock, 5 minutes by default.
^[0-9]+$At least 16 random bytes in base64url, never reused within twice the window.
22 - 128^[A-Za-z0-9_-]+={0,2}$The base64 HMAC-SHA256, under the key's secret, of the method, the path and query, the timestamp, the nonce and the body's SHA-256.
Your id for this request, 1 to 128 printable characters, repeated in the answer; absent, the engine makes one.
128^[\x21-\x7E]+$A W3C trace context, which the engine joins and passes on.
^[0-9a-f]{2}-[0-9a-f]{32}-[0-9a-f]{16}-[0-9a-f]{2}$Path Parameters
The holder's id.
Query Parameters
Only this instrument's records.
Only movements of these kinds; repeat it for several. Absent, every kind.
What moved an account's units.
issue, retire, subscription, redemption, distribution, forced-transfer, recovery, succession, transfer, correction, other Only movements whose ledger time is this instant or later.
Only movements whose ledger time is before this instant.
The most movements a page holds, 1 to 1000; absent, 100.
1 <= x <= 1000The ledger offset to read at, instead of the latest; not with asOf. What depends on time is judged at the offset's ledger time.
An instant to read the ledger as it stood then; not with at. What depends on time is judged at that instant.
The previous page's next; absent, the first page.
Response
The movements.
The ledger offset the answer was read at; 0 for an answer from the engine's own records.
The ledger time of offset: the effective time of the latest transaction at or before it; null where the projection records none.
The engine's clock when it answered, an ISO-8601 instant.
What the read answers; for a list, the page's records in the list's order.
Show child attributes
Show child attributes
The cursor for the next page, sent back as after; null on a list's last page, never on a feed.

