Earnings, payouts and transactions
All financial endpoints require an owner session (Nano, explicit Base SIWX or verified email). Publishing keys and resource-only wallet proofs have no financial-read or recipient-write authority. Responses use private, no-store and the financial problem catalog.
| Method and path | Perspective |
|---|---|
GET /api/v1/earnings | Creator union of accepted sales, Post tips and Comment tips |
GET /api/v1/payouts | The same creator union, including absent/blocked outgoing obligations |
GET /api/v1/transactions | Buyer's own incoming payment receipts |
GET /api/v1/earnings/summary | {summary,total,asOf} for the same filters |
GET /api/v1/{earnings,payouts,transactions}/:sourceKind/:sourceId | One owned source |
PUT /api/v1/payouts/:sourceKind/:sourceId/recipient | Explicit binding of an eligible original missing destination |
GET /api/v1/stats | Creator analytics, separate from raw accounting |
sourceKind is sale, post_tip or post_comment_tip. sourceId is the original purchase/tip UUID; use the pair as the record identity. A payout UUID alone cannot identify all sources. The actual beneficiary of a Comment tip can be its Comment author. Current ownership, Post price and Profile cannot manufacture a historical beneficiary or amount.
Exact record and hash roles
History exposes original_beneficiary_id, approved_beneficiary_id, effective_beneficiary_id and beneficiary_basis (original, operator_historical or unresolved). beneficiary_id equals the effective identity for existing clients. An explicit operator decision can assign an otherwise unknown historical beneficiary; the original field stays null and incomplete original facts remain evidence_state: unresolved, including after a confirmed creator send. A present-day Post association grants unresolved history visibility only while no effective beneficiary exists. Ordinary account routing cannot replace a historical operator decision.
The machine-readable FinancialItem schema defines every returned field. Principal fields are:
| Fields | Meaning |
|---|---|
id,source_kind,source_id,payout_id,purchase_id,kind | Native source and optional creator payout references |
gross_amount_raw,commission_amount_raw,net_amount_raw | Actual original decimal raw strings, or null if evidence is incomplete |
beneficiary_id,recipient_address,resolution_eligible,evidence_state | Effective beneficiary, bound routing and explicit unresolved/eligible state |
created_at,received_at,paid_at | Incoming acceptance time; creator confirmed-send time is separate and nullable |
reference | Original available {post_id,post_title,post_handle,comment_id} |
incoming_hash | Buyer/tipper send to the allocated source account |
receive_hash | Platform receive into that source account |
block_hash | Creator outgoing send hash; check paid/confirmed time for confirmation |
commission_hash | Platform commission outgoing send hash; check its independent state |
creator_expected_hash,creator_submitted_hash,commission_expected_hash | Prepared/submitted evidence, not confirmed payout |
commission_status,commission_paid_at,payout_legs | Independent creator/commission operations, statuses, amounts and available hashes |
corroborating_hashes,error_message,purchase_card | Original identity corroboration, unresolved reason and buyer-only legacy card context |
Each payout_legs.creator includes {operation_id,status,amount_raw,address,block_hash,expected_hash,submitted_hash,confirmed_at}. The commission leg has the same transfer evidence without a recipient address. Buyer histories redact the creator receiving address. Unknown amounts/hash/timestamps stay null; they are never replaced with today's price, zero, a buyer hash or the other leg's hash.
Use arbitrary-precision integers: gross = fee + net. 1 XNO = 10^30 raw. The original session snapshots its fee policy; current defaults are 750 basis points for Nano sales, 1500 for USDC sales and 500 for Nano tips, with recorded integer split/rounding. Historical facts govern; never apply one blanket fee to all sources. A missing or nonconserving split is unresolved. Hash presence alone is not payout confirmation.
Status and totals
Creator status is pending, blocked, processing, submitted, needs_reconciliation, paid or failed. Blocked missing-address obligations remain owed without consuming a transfer attempt. Prepared/submitted operations remain visible before native outgoing checkpoints are repaired. paid requires creator confirmed-send evidence; it does not prove the creator wallet has signed its receive or can spend those funds. A confirmed commission never makes the creator paid. Incoming receipt, platform receive, purchase entitlement and creator payout are independent.
summary and each source_breakdown entry contain count, gross_raw, net_raw, commission_raw, earned_raw, unpaid_raw, confirmed_sent_raw, unresolved_count, last_payout_at. Known complete facts conserve totals; aggregates affected by unknown splits are null, with unresolved count. Confirmed-sent raw starts at "0" when none are proven. earned_raw means accepted creator amount owed, not a spendable wallet balance. Totals cover the entire selected scope rather than one page.
Filters and stable traversal
Lists return {items,total,summary,pagination:{asOf,nextCursor}}.
| Query | Supported values |
|---|---|
type | all, tip (both tip kinds), sale, post_tip, post_comment_tip |
status | Comma-separated creator statuses |
startDate,endDate | Inclusive ISO date or timestamp; start must not exceed end |
limit | 1–50, default 50 |
asOf | Nonfuture ISO issuance watermark; optional on first request |
cursor | Opaque continuation returned by the previous page |
Rows order by received_at descending, source_kind in C order descending, then source_id descending; unknown dates follow known dates. Retain the same filters/perspective and copy nextCursor verbatim; it preserves asOf and the last position. Wrong filter identity, repeated scalar values, future watermark, malformed cursor or invalid date returns 400. Changing limit is allowed. New accepted sources after asOf do not enter that traversal. Payout status and unresolved evidence can change while traversing; asOf is not a historical database snapshot. Deduplicate by the native pair and restart a fresh traversal for an updated report.
USDC receipts and separate asset totals
USDC rows identify asset:"USDC", their exact network and decimals:6. source_id is the distinct incoming receipt UUID; purchase_id links the shared Post entitlement. Preserve both rather than deduplicating separate transfers by purchase. An exceptional second receipt has receipt_disposition:"needs_reconciliation" and does not create another automatic commission or creator payout.
Read gross_amount_atomic, commission_amount_atomic and net_amount_atomic for tagged amounts. The legacy *_raw fields and summary remain Nano-only; a USDC row leaves its Nano amounts null. asset_summaries contains one group per asset/network with exact gross_atomic, commission_atomic, net_atomic, earned_atomic, unpaid_atomic, confirmed_sent_atomic and unresolved_count. Never add these groups together.
Use asset=USDC&network=eip155:8453 or asset=XNO&network=nano-mainnet to scope a history. Base Sepolia evidence uses eip155:84532. Supply both fields together; changing either invalidates the continuation cursor. Untagged requests return both kinds of receipts while retaining Nano scalar totals.
The creator obligation remains visible if absent, blocked or submitted. payout_reason explains recovery, including missing gas. Buyer access survives a delayed payout. gas_costs reports outgoing transaction evidence in ETH wei (18 decimals): L2, L1 and operator fees, plus total_fee_wei. Unavailable fee components and totals stay null; synthetic or incomplete receipts do not establish a zero cost. Creator USDC debt is not reduced by these platform costs. The saved Base destination applies to each frozen sale; the Nano recipient-binding endpoint does not reroute USDC obligations.
Resolve an eligible missing recipient
Saving an address affects new allocations. Binding an earlier missing recipient is a deliberate, separate owner action and performs no transfer.
- GET the saved payout address and exact
updatedAtrevision. - Read the financial source. Require
resolution_eligible: trueand your originalbeneficiary_id. - PUT the source recipient with that exact pair:
PUT /api/v1/payouts/post_tip/<sourceId>/recipient
Authorization: Bearer <ownerAccessToken>
Content-Type: application/json
{"payoutAddress":"<saved Nano address>","addressUpdatedAt":"<exact saved updatedAt>"}
The active owner, saved validated address/revision and original conserving payment evidence are checked under the publication/operation locks. A source already carrying a destination, attempt or creator send intent cannot be redirected. Success records original source/beneficiary/amount and resolution provenance, returns recipientAddress,addressUpdatedAt,resolvedAt,beneficiaryId,amountRaw,status:"pending" plus the saved snake-case evidence. The same binding replays that result; different intent/stale revision returns 409 recipient-resolution-conflict. Missing/ineligible owner source can return 404.
An unresolved original beneficiary/split is never inferred from the current Post or wallet. Such recovery uses an operator-reviewed dry run and separate approval; ordinary account APIs cannot send/drain/retry another user's payout or change fees.
Creator analytics
GET /api/v1/stats?window=7d&sort=visits_desc&metrics=visits,unlocks returns {rows,trend,top_posts,previous_totals,refreshed_at,window,bucket,metrics}. Windows: 7d, 30d, lifetime. Sorts: visits_desc, unlocks_desc, comments_desc, tips_desc, total_revenue_desc, unlock_revenue_desc, tip_revenue_desc. Metrics: visits, unlocks, comments, tips, total/unlock/tip revenue XNO, and unlock_revenue_usdc (the creator share of USDC sales on this deployment's Base network, never converted into XNO); optional post=<UUID> scopes a Post. Invalid window/sort use defaults; metrics normalize to supported entries. Tips and tip revenue count paid Post tips and paid Comment tips that went to the Post owner, across all history; a tip on a reader's Comment is that reader's. The XNO revenue fields and the revenue sorts never include USDC. Numeric analytics are for reporting; use raw financial history for reconciliation.
previous_totals contains every metric above for the immediately preceding 7-day or 30-day period, using the same owner and Post scope. It is null for lifetime or an unavailable comparison.