ReferenceSpec
Receipt Query API
The trust-control receipt read routes: filters, cursor pagination, analytics and operator-report bodies, and the CLI and SDK clients.
Source
The crate is the contract; no specification file covers these routes. This page reflects crates/platform/chio-control-plane/src/trust_control/service_types/paths.rs (the path constants and the list limits), service_types/requests.rs (the query and response types), service_runtime/router.rs (which handler each path is registered against), trust_control/receipt_handlers.rs and trust_control/report_validation.rs (authentication and status codes).
The response bodies come from crates/kernel/chio-kernel/src/receipt_analytics.rs and crates/kernel/chio-kernel/src/operator_report/, and the SQL behind them from crates/platform/chio-store-sqlite/src/receipt_store/reports/. The CLI flags come from crates/products/chio-cli/src/cli/types/receipt.rs, and the clients from sdks/typescript/chio-ts/src/receipt_query_client.ts and sdks/python/chio-py/src/chio/receipt_query.py. Status: shipped.
Synopsis
4 routes read receipts. Each takes its filters from the query string and returns JSON.
| Method | Path | Query type | Response type |
|---|---|---|---|
| GET | /v1/receipts/query | ReceiptQueryHttpQuery | ReceiptQueryResponse |
| GET | /v1/agents/{subject_key}/receipts | AgentReceiptsHttpQuery | ReceiptQueryResponse |
| GET | /v1/receipts/analytics | ReceiptAnalyticsQuery | ReceiptAnalyticsResponse |
| GET | /v1/reports/operator | OperatorReportQuery | OperatorReport |
Endpoint summary
Two further receipt routes read the same store behind a different envelope. /v1/receipts/tools takes ToolReceiptQuery and /v1/receipts/children takes ChildReceiptQuery; both accept a receiptId that point-loads exactly one row, which is how a deployment resolves a parent or child receipt the kernel's bounded in-memory mirror has evicted. Both return ReceiptListResponse: configured, backend, kind, count, filters, and receipts, with no cursor. The child listing is admin-only: a tenant read token gets 403, because child receipts carry no tenant attribution. POST appends a receipt, requires the service token, forwards to the cluster leader, and carries a body-size limit.
| Method | Path | Purpose |
|---|---|---|
| GET | /v1/receipts/query | Receipt query with filters and cursor pagination |
| GET | /v1/agents/{subject_key}/receipts | Agent-scoped listing; accepts limit and cursor only |
| GET | /v1/receipts/analytics | Aggregate counters and groupings over the same corpus |
| GET | /v1/reports/operator | Composed operator report over the receipt and budget stores |
| GET, POST | /v1/receipts/tools | List or append tool receipts |
| GET, POST | /v1/receipts/children | List or append child receipts |
Every route requires a bearer token in the Authorization header. The filters combine with AND semantics, and omitting a parameter disables that filter.
Authentication
The trust-control server compares the bearer token against two sets in constant time and resolves one of two principals: the admin service token, or a per-tenant read token. The principal becomes the read context the store query runs under, so a tenant token reads only that tenant's receipts.
curl -sS https://trust.example.com/v1/receipts/query \
-H "Authorization: Bearer my-service-token"The operator provisions tokens out of band, alongside chio trust serve. /v1/receipts/query and /v1/agents/{subject_key}/receipts accept either principal. The analytics and operator-report routes accept the admin service token only: a tenant read token gets 403 with the message <surface> requires admin receipt read authority.
Treat tokens like keys
CHIO_CONTROL_TOKEN environment variable over the argv form, which leaks through ps.Filter parameters
Every parameter is a query-string parameter. The names are camelCase on the wire, because ReceiptQueryHttpQuery carries serde(rename_all = "camelCase").
| Parameter | Type | Description |
|---|---|---|
capabilityId | string | Exact match on capability id |
toolServer | string | Exact match on tool server name |
toolName | string | Exact match on tool name |
outcome | string | One of allow, deny, cancelled, incomplete; maps to the decision_kind column |
since | u64 | Only receipts with timestamp >= since (Unix seconds, inclusive) |
until | u64 | Only receipts with timestamp <= until (Unix seconds, inclusive) |
minCost | u64 | Minimum cost_charged in minor units. Receipts without financial metadata are excluded when it is set. |
maxCost | u64 | Maximum cost_charged in minor units. Receipts without financial metadata are excluded when it is set. |
costCurrency | string | Currency for the cost bounds, a three-letter uppercase code. Required whenever minCost or maxCost is present. |
agentSubject | string | Hex-encoded Ed25519 agent subject key, resolved through the capability-lineage join rather than by replaying issuance logs |
cursor | u64 | Pagination cursor. Returns only receipts with seq > cursor (exclusive). |
limit | usize | Results per page. Clamped to the range 1 to 200; the default when absent is 50. |
The server validates the cost filters before it touches the store. A minimum above the maximum, a cost bound with no costCurrency, or a currency that is not three uppercase ASCII letters each return 400 with the reason in the error string.
The server cap is authoritative
limit passes through list_limit, which clamps the requested value into the range fixed by DEFAULT_LIST_LIMIT and MAX_LIST_LIMIT. A larger value is reduced without an error. The TypeScript and Python ReceiptQueryClient helpers forward limit unchanged and follow nextCursor; they add no higher logical cap and no double fetch. Size bandwidth around 200-item pages.Response shape
{
"totalCount": 1024,
"nextCursor": 47,
"receipts": []
}ReceiptQueryResponse has exactly those three fields. totalCount counts every receipt matching the filters, independent of page limit and cursor, so a caller renders a total without paginating to the end.
nextCursor is the seq of the last receipt in the page, and the store sets it only when the page came back full. A short page means no more rows matched, and the field serializes as null. Pass a non-null value back as cursor to fetch the next page.
receipts holds the stored ChioReceipt values, serialized one for one and ordered by seq ascending. The handler serializes the stored receipt without rewriting it, so the signature still covers what the array carries and a client can check it against the kernel key. Receipt Format documents the fields.
Cursor pagination
The cursor is the seq column value of the last receipt in a page. Pagination is forward-only and append-safe: new receipts land at higher seq values and appear on later pages without moving the boundaries of a page already read.
# Page 1
GET /v1/receipts/query?toolServer=shell&limit=50
# Response carries nextCursor: 147
# Page 2
GET /v1/receipts/query?toolServer=shell&limit=50&cursor=147
# nextCursor is null on the last page.The cursor is a raw u64. Treat the value as opaque: round-trip what the server returned in nextCursor rather than parsing or constructing cursors.
Example request
GET /v1/receipts/query?outcome=deny&since=1700000000&limit=2
Authorization: Bearer my-service-tokenThe array elements are the receipts the kernel wrote. The CLI reads the same store and prints the same objects, one per line, so the shape below is what an HTTP caller iterates over as well.
$ chio --receipt-db .chio/receipts.db receipt list --admin-all \
| jq 'select(.decision.verdict == "deny")'{
"id": "28b6e2576ca2ccbd031e769d8d2bd504317161115a600f27771a7f932307a284",
"timestamp": 1788529912,
"capability_id": "cap-01a06cb0-aae3-7ad3-8ba7-01350a3e01a0",
"tool_server": "hello",
"tool_name": "drop_tables",
"action": {
"parameters": {},
"parameter_hash": "44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a"
},
"decision": {
"verdict": "deny",
"reason": "requested tool drop_tables on server hello is not in capability scope",
"guard": "kernel"
},
"receipt_kind": "mediated_decision",
"boundary_class": "prevent",
"tool_origin": "caller_executed",
"redaction_mode": "none",
"content_hash": "74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b",
"policy_hash": "69e943b96e9ce64d0264bb56bf8930e77bd4e68adf68fcf1395790dae03e6b55",
"metadata": {
"attribution": {
"delegation_depth": 0,
"issuer_key": "3dbf7b1230475796d5c78cdcf441c84721d9e3c24362fbbfb4225e307d1b9fb4",
"subject_key": "af2da8097f2c133affd89145302f029c7a5854e4e3a692a92b0cd20f84d07b37"
},
"chio_receipt_signing_nonce": "rcpt-01a06cb0-ab51-70d0-bcb3-72a8b78fe057",
"receipt_context": {
"request_id": "check-001"
}
},
"trust_level": "mediated",
"kernel_key": "3dbf7b1230475796d5c78cdcf441c84721d9e3c24362fbbfb4225e307d1b9fb4",
"signature": "e89f7a9cbe6c6b207cf5ac0c3e197a3957d62d2994217a7dcaeeeb9869abef1233680328432ee7a502a76238eb6ee9e72b19715e2458a3ef85aebfbed0df9202"
}A denial is a row in the same corpus as an allow, with the refused parameters still attached. Filtering outcome=deny is how an auditor reads the refusals without reading the whole log.
Agent-scoped route
A shorter URL covers per-agent lookups.
GET /v1/agents/{subject_key}/receipts?limit=50&cursor=0
Authorization: Bearer my-service-tokenAgentReceiptsHttpQuery carries cursor and limit and nothing else, so the subject key in the path is the only filter. The response type is the same ReceiptQueryResponse. Use it when a routing layer makes per-agent path scoping easier than a query string.
TypeScript SDK
@chio-protocol/sdk ships a ReceiptQueryClient over this route. The constructor takes positional arguments: new ReceiptQueryClient(baseUrl, authToken, fetchImpl?). query(params) fetches one page. paginate(params) is an async generator yielding one array of receipts per page, and it throws QueryError when the returned cursor fails to advance rather than looping.
import { ReceiptQueryClient } from "@chio-protocol/sdk";
const client = new ReceiptQueryClient(
"https://trust.example.com",
process.env.CHIO_CONTROL_TOKEN!,
);
// Single page.
const page = await client.query({
outcome: "deny",
since: 1700000000,
limit: 50,
});
console.log(`${page.totalCount} total denies`);
for (const receipt of page.receipts) {
console.log(receipt.id, receipt.decision);
}
// paginate() yields one array of receipts per page.
for await (const receipts of client.paginate({
toolServer: "payment-server",
since: 1700000000,
})) {
for (const receipt of receipts) {
if (receipt.decision?.verdict === "deny") {
console.warn(`denied: ${receipt.decision.reason}`);
}
}
}Python SDK
The chio.ReceiptQueryClient constructor is ReceiptQueryClient(base_url, auth_token, *, client=None). The keyword is auth_token, not bearer_token. query() and paginate() are synchronous: the default transport is a blocking urllib request, and passing client= substitutes an object with a get() method. Filters are a dict of the same camelCase keys the route accepts, and paginate() yields one list of receipts per page.
import os
from chio import ReceiptQueryClient
client = ReceiptQueryClient(
"https://trust.example.com",
auth_token=os.environ["CHIO_CONTROL_TOKEN"],
)
# Single page. query() and paginate() are synchronous.
page = client.query({"outcome": "deny", "since": 1700000000, "limit": 50})
print(f"{page['totalCount']} total denies")
for receipt in page["receipts"]:
print(receipt["id"], receipt.get("decision"))
# paginate() yields one list of receipts per page.
for receipts in client.paginate({"toolServer": "payment-server", "since": 1700000000}):
for receipt in receipts:
decision = receipt.get("decision")
if decision and decision["verdict"] == "deny":
print(f"denied: {decision['reason']}")Both clients thread the cursor and stop when the server returns no nextCursor. Neither refreshes tokens, retries a transient error, or verifies receipt signatures.
Pagination without an SDK
In a language with no client, the loop is short.
cursor=""
while : ; do
resp=$(curl -sS \
"https://trust.example.com/v1/receipts/query?outcome=deny&limit=200${cursor:+&cursor=$cursor}" \
-H "Authorization: Bearer $CHIO_CONTROL_TOKEN")
echo "$resp" | jq -r '.receipts[].id'
cursor=$(echo "$resp" | jq -r '.nextCursor // empty')
[ -z "$cursor" ] && break
doneAnalytics route
/v1/receipts/analytics aggregates the same corpus in the store. ReceiptAnalyticsQuery takes capabilityId, agentSubject, toolServer, toolName, since, and until, plus two aggregation parameters. It has no cost filters and no cursor.
| Parameter | Description |
|---|---|
groupLimit | Rows per grouped dimension. The store clamps it to the range 1 to MAX_ANALYTICS_GROUP_LIMIT, which is 200; the query default is 50. |
timeBucket | Bucket width, hour (3600 seconds) or day (86400 seconds). Default day. |
{
"summary": {
"totalReceipts": 12,
"allowCount": 9,
"denyCount": 1,
"cancelledCount": 1,
"incompleteCount": 1,
"totalCostCharged": 750,
"totalAttemptedCost": 500,
"reliabilityScore": 0.8181818182,
"complianceRate": 0.9166666667,
"budgetUtilizationRate": 0.6
},
"byAgent": [{ "subjectKey": "", "metrics": {} }],
"byTool": [{ "toolServer": "shell", "toolName": "bash", "metrics": {} }],
"byTime": [{ "bucketStart": 1700000000, "bucketEnd": 1700086400, "metrics": {} }]
}Every row carries the same ReceiptAnalyticsMetrics under metrics. The three ratios are Option<f64> and are omitted from the JSON when their denominator is zero: reliabilityScore divides allows by allows plus cancelled plus incomplete, complianceRate divides non-denies by total receipts, and budgetUtilizationRate divides charged cost by charged plus attempted cost. The other seven fields are u64 and always present.
Operator report route
/v1/reports/operator composes the analytics, cost-attribution, budget, compliance, settlement, metered-billing, authorization-context, and shared-evidence slices into one body, reading the receipt store and the budget store in one request.
OperatorReportQuery takes the analytics filters and aggregation parameters, plus six row limits, each defaulting to the value shown.
| Parameter | Default | Bounds the rows in |
|---|---|---|
attributionLimit | 100 | costAttribution |
budgetLimit | 50 | budgetUtilization |
settlementLimit | 50 | settlementReconciliation |
meteredLimit | 50 | meteredBillingReconciliation |
authorizationLimit | 50 | authorizationContext |
economicLimit | 50 | the economic receipt projection |
OperatorReport declares no optional top-level key, so a client indexes every one below without a presence check.
{
"generatedAt": 1700000000,
"filters": { "toolServer": "shell", "toolName": "bash" },
"activity": {},
"costAttribution": {},
"budgetUtilization": { "summary": {}, "rows": [] },
"compliance": {},
"settlementReconciliation": { "summary": {}, "receipts": [] },
"meteredBillingReconciliation": { "summary": {}, "receipts": [] },
"authorizationContext": { "schema": "", "profile": {}, "summary": {}, "receipts": [] },
"sharedEvidence": { "summary": {}, "references": [] }
}| Key | Type | Carries |
|---|---|---|
generatedAt | u64 | Unix seconds the report was built |
filters | OperatorReportQuery | The filters as the server resolved them; the read context is never serialized |
activity | ReceiptAnalyticsResponse | The same body the analytics route returns |
costAttribution | CostAttributionReport | The same body /v1/reports/cost-attribution returns |
budgetUtilization | BudgetUtilizationReport | A summary and one row per capability grant, with invocation and cost usage |
compliance | ComplianceReport | Checkpoint and lineage coverage, settlement backlog counts, and the evidence-export query |
settlementReconciliation | SettlementReconciliationReport | A summary and the receipts awaiting settlement reconciliation |
meteredBillingReconciliation | MeteredBillingReconciliationReport | A summary and the receipts awaiting metered-billing reconciliation |
authorizationContext | AuthorizationContextReport | A schema id, the OAuth authorization profile, a summary, and one row per receipt |
sharedEvidence | SharedEvidenceReferenceReport | A summary and one row per federated evidence share matched to local receipts |
compliance carries childReceiptScope, whose value is one of full_query_window, time_window_context_only, or omitted_no_join_path. It says how far an evidence export over the same filters would reach for child receipts.
The other report routes
The operator report is one of the routes the trust-control router registers under /v1/reports/. The other 32 cover credit, liability, settlement, authorization, and underwriting surfaces, and each has its own request and response type.
| Method | Path | Handler |
|---|---|---|
| GET | /v1/reports/authorization-context | handle_authorization_context_report |
| GET | /v1/reports/authorization-profile-metadata | handle_authorization_profile_metadata_report |
| GET | /v1/reports/authorization-review-pack | handle_authorization_review_pack_report |
| GET | /v1/reports/behavioral-feed | handle_behavioral_feed_report |
| GET | /v1/reports/bond-loss-policy | handle_credit_loss_lifecycle_report |
| GET | /v1/reports/bond-losses | handle_query_credit_loss_lifecycle |
| GET | /v1/reports/bond-policy | handle_credit_bond_report |
| POST | /v1/reports/bonded-execution-simulation | handle_credit_bonded_execution_simulation_report |
| GET | /v1/reports/bonds | handle_query_credit_bonds |
| GET | /v1/reports/capital-book | handle_capital_book_report |
| GET | /v1/reports/comptroller-surface | handle_comptroller_surface_report |
| GET | /v1/reports/cost-attribution | handle_cost_attribution_report |
| GET | /v1/reports/credit-backtest | handle_credit_backtest_report |
| GET | /v1/reports/credit-scorecard | handle_credit_scorecard_report |
| GET | /v1/reports/economic-completion-flow | handle_economic_completion_flow_report |
| GET | /v1/reports/economic-receipts | handle_economic_receipt_report |
| GET | /v1/reports/exposure-ledger | handle_exposure_ledger_report |
| GET | /v1/reports/facilities | handle_query_credit_facilities |
| GET | /v1/reports/facility-policy | handle_credit_facility_report |
| GET | /v1/reports/liability-claims | handle_query_liability_claim_workflows |
| GET | /v1/reports/liability-market | handle_query_liability_market_workflows |
| GET | /v1/reports/liability-providers | handle_query_liability_providers |
| GET | /v1/reports/metered-billing | handle_metered_billing_report |
| GET | /v1/reports/provider-risk-package | handle_credit_provider_risk_package_report |
| POST | /v1/reports/runtime-attestation-appraisal | handle_runtime_attestation_appraisal_report |
| POST | /v1/reports/runtime-attestation-appraisal-result | handle_runtime_attestation_appraisal_result_export |
| POST | /v1/reports/runtime-attestation-appraisal/import | handle_runtime_attestation_appraisal_import |
| GET | /v1/reports/settlements | handle_settlement_report |
| GET | /v1/reports/underwriting-decision | handle_underwriting_decision_report |
| GET | /v1/reports/underwriting-decisions | handle_query_underwriting_decisions |
| GET | /v1/reports/underwriting-input | handle_underwriting_policy_input |
| POST | /v1/reports/underwriting-simulation | handle_underwriting_simulation_report |
The chio receipt list subcommand
chio receipt list reads the same corpus, from a local SQLite receipt store or over HTTP. It prints one JSON receipt per line.
chio receipt list [OPTIONS]
Options:
--capability <ID> Filter by capability ID
--tool-server <NAME> Filter by tool server ID
--tool-name <NAME> Filter by tool name
--outcome <OUT> allow | deny | cancelled | incomplete
--since <SEC> Receipts with timestamp >= this Unix seconds value
--until <SEC> Receipts with timestamp <= this Unix seconds value
--min-cost <UNITS> Minimum cost in minor units; requires --cost-currency
--max-cost <UNITS> Maximum cost in minor units; requires --cost-currency
--cost-currency <CODE> Three-letter uppercase currency code for the cost filters
--limit <N> Maximum receipts per page [default: 50]
--cursor <SEQ> Cursor for pagination (seq value to start after)
--tenant <ID> Tenant read boundary; conflicts with --admin-all
--admin-all Read across all tenants as an administrative operation
Global options that apply here:
--receipt-db <PATH> SQLite database path for durable receipt persistence
--control-url <URL> Shared trust-control service base URL
--control-token <TOK> Bearer token for the trust-control service--min-cost and --max-cost each declare requires = "cost_currency", so clap rejects either one on its own. That mirrors the HTTP route, where a cost bound without costCurrency is a 400.
Local reads need an explicit read boundary
--receipt-db mode the read path fails closed unless exactly one of --tenant <ID> or --admin-all is supplied. The two conflict: --admin-all declares conflicts_with = "tenant". Against a running server the scope comes from the control token instead.$ chio --receipt-db .chio/receipts.db receipt list --admin-all \
| jq -r '[.decision.verdict, .tool_server, .tool_name, .id] | @tsv'allow hello hello_world 448440b65fa15559a364d24512cbe4f08631befe2c3d2ab471dad7204b8b69c8 deny hello drop_tables 28b6e2576ca2ccbd031e769d8d2bd504317161115a600f27771a7f932307a284
Piping the same command through jq selects one verdict and prints the whole receipt.
$ chio --receipt-db .chio/receipts.db receipt list --admin-all \
| jq 'select(.decision.verdict == "deny")'{
"id": "28b6e2576ca2ccbd031e769d8d2bd504317161115a600f27771a7f932307a284",
"timestamp": 1788529912,
"capability_id": "cap-01a06cb0-aae3-7ad3-8ba7-01350a3e01a0",
"tool_server": "hello",
"tool_name": "drop_tables",
"action": {
"parameters": {},
"parameter_hash": "44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a"
},
"decision": {
"verdict": "deny",
"reason": "requested tool drop_tables on server hello is not in capability scope",
"guard": "kernel"
},
"receipt_kind": "mediated_decision",
"boundary_class": "prevent",
"tool_origin": "caller_executed",
"redaction_mode": "none",
"content_hash": "74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b",
"policy_hash": "69e943b96e9ce64d0264bb56bf8930e77bd4e68adf68fcf1395790dae03e6b55",
"metadata": {
"attribution": {
"delegation_depth": 0,
"issuer_key": "3dbf7b1230475796d5c78cdcf441c84721d9e3c24362fbbfb4225e307d1b9fb4",
"subject_key": "af2da8097f2c133affd89145302f029c7a5854e4e3a692a92b0cd20f84d07b37"
},
"chio_receipt_signing_nonce": "rcpt-01a06cb0-ab51-70d0-bcb3-72a8b78fe057",
"receipt_context": {
"request_id": "check-001"
}
},
"trust_level": "mediated",
"kernel_key": "3dbf7b1230475796d5c78cdcf441c84721d9e3c24362fbbfb4225e307d1b9fb4",
"signature": "e89f7a9cbe6c6b207cf5ac0c3e197a3957d62d2994217a7dcaeeeb9869abef1233680328432ee7a502a76238eb6ee9e72b19715e2458a3ef85aebfbed0df9202"
}Omitting the boundary is an error rather than a default, and so is supplying both.
chio receipt list --receipt-db ./chio.db --outcome deny
chio receipt list --receipt-db ./chio.db --tenant acme --admin-allThe first exits with the CLI error domain, because the read path refuses to infer a boundary. The second is rejected by clap before the command runs, from the conflicts_with declaration.
To paginate from the CLI, take nextCursor from one invocation and pass it as --cursor on the next. The SDK paginate() helpers do that threading for a caller.
Rate limits
The receipt query, analytics, and report routes carry no per-token request-rate middleware. The router applies a body-size limit to the POST routes and one response-header layer that sets a Content-Security-Policy on every response; the rate limiters in the crate govern federation admission and cluster peer authentication, not these read paths. Size a scan accordingly: prefer /v1/reports/operator for a dashboard, and reuse nextCursor rather than re-scanning from the start.
Error responses
Every error path on these handlers returns a JSON object with one error string, built by plain_http_error. There is no nested code object and no machine-readable error registry on these routes. Read the status for the class of failure and the string for the detail.
{ "error": "missing or invalid control bearer token" }A request with no bearer token and a request with a token the server does not hold land on the same response: 401, that body, and a www-authenticate: Bearer header.
| HTTP | Meaning |
|---|---|
| 400 | Cost filters failed validation: a minimum above the maximum, a bound with no costCurrency, or a currency that is not three uppercase letters |
| 401 | Missing or invalid bearer token |
| 403 | A tenant read token reached an admin-only surface, or asked for another tenant |
| 500 | The service config failed validation, the store would not open, or serialization failed; the string carries the detail |
Operational notes
- Ordering. A page returns receipts by
seqascending. New receipts append at higherseqvalues, so a long-running forward pagination reaches new data without repeating old data. - Signature verification. The handler serializes the stored receipt unchanged, so the kernel signature over the canonical body survives the round trip. Verify it against the kernel key with the bindings helpers before treating a copied receipt as evidence.
- Backfill. A large historical log takes a while to scan end to end. Start with a tight
sincebound and widen the window. The operator report gives a current-state picture in one request. - Read authority. The read context comes from the token, never from a query parameter. The query types that carry a
read_contextfield mark itserde(skip), so a caller cannot set it on the wire.
Related
- Receipt Format: the field semantics of the
ChioReceiptobjects this route returns. - Receipt Dashboard: the hosted UI over these routes and the operator report.
- SDK Overview: the client libraries that wrap this API.
- CLI Reference:
chio receipt listand the other receipt subcommands.