Skip to main content
GET /v2/merchant/x402-earnings returns the authenticated merchant’s rollup of x402 settlement events: per-row settlement detail, totals envelope (settlement amount + count), and pagination. This endpoint is the data source for the merchant x402 Earnings page in the dashboard.
This endpoint requires:
  • Merchant JWT — any authenticated merchant role (OWNER, MEMBER, PRODUCER)
The merchant scope is derived from the JWT sub claim. There is no merchantId query parameter. If a client passes one anyway it is silently ignored — the response is always scoped to the JWT-bound merchant.

GET /v2/merchant/x402-earnings

Authentication

GuardRequirement
JWTRequired, any authenticated merchant role
ScopemerchantId derived from JWT subnot from query / body
Obtain a merchant JWT via POST /merchant/admin/login — see Authentication.

Query parameters

ParamTypeRequiredDefaultDescription
pageintegerNo11-indexed page number.
limitintegerNo20Rows per page.
startDateISO-8601 stringNoFilter to settlements with settledAt >= startDate. Omit for no lower bound.
endDateISO-8601 stringNoFilter to settlements with settledAt <= endDate. Omit for no upper bound.

Example

curl "https://apiv3.droplinked.com/v2/merchant/x402-earnings?page=1&limit=20" \
  -H "Authorization: Bearer <MERCHANT_JWT>"
With a date filter:
curl "https://apiv3.droplinked.com/v2/merchant/x402-earnings?page=1&limit=20&startDate=2026-01-01T00:00:00Z&endDate=2026-06-14T23:59:59Z" \
  -H "Authorization: Bearer <MERCHANT_JWT>"

Response — 200 OK

{
  "rows": [],
  "totalSettlementsUsdCents": 0,
  "totalCount": 0,
  "asOf": "2026-06-14T23:41:10.180Z",
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 0
  }
}

Fields

FieldTypeNullableDescription
rowsarrayNoOne entry per x402 settlement event matching the filter. Empty array until X402_ENABLED is flipped on, or when the merchant has no settlements in the filter window.
rows[].settlementIdstringNoX402SettlementLog row _id.
rows[].settledAtISO-8601 stringNoSettlement timestamp (UTC) — when the x402 settlement event was captured on chain and recorded.
rows[].amountUsdCentsintegerNoSettlement amount in USD cents, integer. x402 settles natively in USDC on Base; the read path snapshots the FX at settlement time.
rows[].productIdstringYesSource product _id if the settlement is tied to a specific product. null for storefront-wide payouts.
rows[].orderIdstringYesSource order _id if available. null for legacy rows.
rows[].txHashstringYesBase transaction hash. null for legacy rows pre-dating chain-hash capture.
totalSettlementsUsdCentsintegerNoSum of amountUsdCents for the merchant across the filter window (not just the current page).
totalCountintegerNoTotal settlement count for the merchant across the filter window.
asOfISO-8601 stringNoSnapshot timestamp (server clock, UTC).
paginationobjectNoPagination envelope.
pagination.pageintegerNoEchoed page query param (1-indexed).
pagination.limitintegerNoEchoed limit query param.
pagination.totalintegerNoTotal number of settlement rows matching the filter (across pages). Equal to totalCount.

Errors

StatusBodyWhen
401{ "statusCode": 401, "status": "failed", "data": { "message": "Unauthorized" } }Missing or invalid JWT
5xx{ "statusCode": 500, "status": "failed", ... }Hard backend failure — see Notes below for the fail-open contract

Notes

  • X402_ENABLED gating. Until the platform flag X402_ENABLED is set to true, X402SettlementLog accepts no writes and this endpoint always returns rows: [], totalSettlementsUsdCents: 0, totalCount: 0. The endpoint itself is always reachable — the gate is at the write path, not the read path. Merchants safely linkable to the page before the flip; it renders an empty-state.
  • Auth scope. The endpoint reads merchantId from the JWT sub claim only. Any ?merchantId= is silently ignored. A merchant cannot read another merchant’s settlements through this endpoint — even with a syntactically valid query parameter pointing at the target.
  • Fail-open semantics. If the underlying X402SettlementLog aggregation throws, the endpoint returns the empty-state envelope (rows: [], totals 0) with 200 OK rather than propagating the error. Inspect server logs / Sentry for the underlying failure.
  • Currency. All monetary fields are USD cents, integer — same contract as the admin x402-earnings rollup. Divide by 100 for major-unit display.
  • Pagination. total and totalCount count settlement rows, not products / orders. A merchant with 50 settlements across 3 products reports total: 50, totalCount: 50.
  • Date filter semantics. startDate and endDate are inclusive bounds on settledAt. Omit either to leave that side of the window unbounded; omit both for the full per-merchant history (capped at the merchant’s earliest settlement).