Analytics and reconciliation
App-scoped reporting over the traffic your app originated: payment volume trends, refund analysis, subscription metrics, renewal diagnosis, and app-fee payout auditing.
Compatible with the closed-beta ATM app APIs and versioned ATM event headers. Check atm-api-version on every webhook or XRPC receiver event.
What apps can measure
ATM exposes read-only reporting queries scoped to the traffic your app originated. Every call is authenticated with app service-auth, numbers are always per currency (never summed across currencies), and the reads are free core rails — reporting never becomes pay-to-play.
| getPaymentVolumeTrends | Bucketed payment counts, success counts, and gross settled volume. |
|---|---|
| getRefundAnalysis | Refunds grouped by reason code and status, with settled gross for rate math. |
| getSubscriptionMetrics | Active count, interval-normalized MRR, and windowed new/canceled counts. |
| diagnoseSubscriptionFailure | Coarse failure reason and ATM-authored guidance for one failed renewal. |
| auditFeeDistributions | Row-level audit of your app-fee payouts for reconciliation. |
Payment volume trends
money.atmosphere.analytics.getPaymentVolumeTrends
Bucketed volume for your originated payments: counts, settled counts, and gross cents per currency, plus method and currency rollups.
- Method
- GET
- Auth
- App service-auth
- Retry behavior
- Read-only; cache briefly. Defaults: live environment, day buckets, 30-day window (windowDays caps at 92).
- Idempotency
- Read-only.
- Common errors
- AppNotRegistered, plus standard service-auth errors.
/xrpc/money.atmosphere.analytics.getPaymentVolumeTrends?granularity=day&windowDays=30{
"series": [
{
"bucket": "2026-06-01T00:00:00.000Z",
"currency": "usd",
"count": 42,
"successCount": 40,
"grossAmount": 96800
}
],
"byMethod": [
{ "method": "card", "currency": "usd", "count": 31, "grossAmount": 74200 }
],
"byCurrency": [
{ "currency": "usd", "count": 42, "grossAmount": 96800 }
],
"window": { "granularity": "day", "windowDays": 30, "from": "2026-06-01T00:00:00.000Z", "to": "2026-07-01T00:00:00.000Z" }
}Refund analysis
money.atmosphere.analytics.getRefundAnalysis
Refunds on your originated payments grouped by reason code and status. The summary carries settled gross per currency so you can compute a refund rate without summing across currencies.
- Method
- GET
- Auth
- App service-auth
- Retry behavior
- Read-only; cache briefly. Params: environment, windowDays, currency.
- Idempotency
- Read-only.
- Common errors
- AppNotRegistered, plus standard service-auth errors.
/xrpc/money.atmosphere.analytics.getRefundAnalysis?windowDays=30{
"byReason": [
{
"reasonCode": "requested-by-customer",
"status": "succeeded",
"currency": "usd",
"count": 3,
"amount": 5400
}
],
"summary": [
{ "currency": "usd", "refundCount": 3, "refundedAmount": 5400, "settledCount": 40, "settledGrossAmount": 96800 }
],
"window": { "windowDays": 30, "from": "2026-06-01T00:00:00.000Z", "to": "2026-07-01T00:00:00.000Z" }
}Subscription metrics
money.atmosphere.analytics.getSubscriptionMetrics
Per-currency subscription health for subscriptions your app originated: active count, interval-normalized MRR snapshot, and new/canceled counts inside the window.
- Method
- GET
- Auth
- App service-auth
- Retry behavior
- Read-only; cache briefly. MRR is a current snapshot; newCount and canceledCount are windowed by createdAt/canceledAt.
- Idempotency
- Read-only.
- Common errors
- AppNotRegistered, plus standard service-auth errors.
/xrpc/money.atmosphere.analytics.getSubscriptionMetrics?windowDays=30{
"byCurrency": [
{
"currency": "usd",
"activeCount": 64,
"mrr": 38000,
"newCount": 9,
"canceledCount": 2
}
],
"window": { "windowDays": 30, "from": "2026-06-01T00:00:00.000Z", "to": "2026-07-01T00:00:00.000Z" },
"notes": []
}Diagnose a failed renewal
money.atmosphere.payment.diagnoseSubscriptionFailure
Why did this renewal fail? Returns a coarse reason plus ATM-authored recommended actions — your app owns the customer communication.
- Method
- GET
- Auth
- App service-auth
- Retry behavior
- Read-only. Only the originating app can diagnose a subscription; anything else reads as NotFound (no existence oracle).
- Idempotency
- Read-only.
- Common errors
- NotFound, plus standard service-auth errors. Reasons: payer-declined, payment-method-expired, authentication-required, processor-unavailable, recipient-account-held, recipient-kyc-pending, unknown.
/xrpc/money.atmosphere.payment.diagnoseSubscriptionFailure?subscriptionId=sub_123{
"reason": "payment-method-expired",
"recipientHold": false,
"retryEligible": true,
"recommendedActions": [
"Ask the supporter to update their card, then let the scheduled retry run."
],
"detail": "The saved card expired before this renewal attempt.",
"failedAt": "2026-06-28T09:12:00.000Z"
}Audit app-fee distributions
money.atmosphere.app.auditFeeDistributions
Row-level, cursor-paged audit of your app-fee payouts: what each cycle earned, when it transferred, and any holds, reversals, or clawbacks — enough to reconcile ATM against your own books.
- Method
- GET
- Auth
- App service-auth
- Retry behavior
- Read-only. Returns only rows your app both originated and receives the fee for; carries no buyer PII, payer fields, or connected-account ids.
- Idempotency
- Read-only; keyset cursor pagination.
- Common errors
- AppNotRegistered, plus standard service-auth errors. Statuses: queued, scheduled, transferred, held, reversed, failed.
/xrpc/money.atmosphere.app.auditFeeDistributions?environment=live&status=transferred{
"distributions": [
{
"id": "dist_9f2",
"paymentId": "pay_a41",
"chargeId": "in_1TkY...",
"role": "app",
"amount": 120,
"currency": "usd",
"status": "transferred",
"processorTransferId": "tr_1TkZ...",
"period": "2026-06",
"createdAt": "2026-06-27T18:04:11.000Z"
}
],
"cursor": "b3BhcXVl"
}Boundaries
- All reporting is scoped to traffic your app originated — you never see a creator’s other apps or ATM-wide numbers.
- Numbers are per currency. Do not sum cents across currencies.
- Reporting reads are operational views. The ATM ledger and your webhook stream remain the settlement truth.
- Analytics carries no buyer PII: no emails, names, notes, or payment-method details.