# Analytics (https://dev.cosmospay.lat/docs/api/analytics/)

> Account summary, balances and operational logs.

Base URL: `https://api.cosmospay.lat/cosmos-api`

## Overview metrics: totals, settled volume, webhook health, 30-day series

`GET /v1/summary`

The settled volume per asset, and every asset valued in USD at NEAR Intents' current reference price (`volumeUsd`, indicative). Without those prices the USD fields are null and the rest answers as usual.

Requires the `payments:read` scope.

**Responses**

- `200` (`AnalyticsSummaryEntity`): OK
  - `totals` (SummaryTotalsEntity, required): Payment intent counts per status.
  - `volume` (AssetVolumeEntity[], required): Settled volume per chain and asset.
  - `volumeUsd` (string, required): Every settled payment in USD with two decimals, valued at NEAR Intents’ current reference price for each asset (its token list, cached for a few minutes): an indicative figure at today's price, not the price on the day each payment settled. Payments in an asset with no price are left out and counted in `unpriced`. Null only when there were settled payments and NEAR Intents' prices could not be read; `0.00` when nothing settled.
  - `unpriced` (number, required): Settled payments `volumeUsd` leaves out: their asset has no USD price (all of them when NEAR Intents' prices could not be read).
  - `webhooks` (WebhookHealthEntity, required): Webhook endpoints and deliveries of the consumer.
  - `customers` (number, required): Distinct paying accounts.
  - `series` (SeriesPointEntity[], required): 30 daily buckets, pre-seeded so a quiet day is a zero.
  - `recent` (RecentPaymentEntity[], required): The 6 most recently created settled payment intents, newest first.
- `401`: Unauthorized (see Shared responses)
- `403`: Forbidden (see Shared responses)
- `500`: InternalError (see Shared responses)

## Activity per day, week, month or year, with the window before

`GET /v1/summary/series`

Payments, swaps, liquidity operations, webhook deliveries and private payments, each grouped into the buckets of `period` (UTC, weeks from Monday, a quiet bucket a zero), with the totals of the window and of the window before, for growth. Payments carry their settled volume in USD too (`volumeUsd`), each asset valued at NEAR Intents' current reference price (indicative). Without those prices the USD fields are null and the rest answers as usual.

Requires the `payments:read` scope.

**Query parameters**

- `period` (string, optional): day: 30 days, week: 12 weeks, month: 12 months, year: 5 years. One of: `day`, `week`, `month`, `year`.

**Responses**

- `200` (`AnalyticsSeriesEntity`): OK
  - `period` (string, required): How the buckets are grouped, as requested (`day` when omitted). One of: `day`, `week`, `month`, `year`.
  - `buckets` (SeriesBucketEntity[], required): 30 days, 12 weeks, 12 months or 5 years, oldest first, pre-seeded so a quiet bucket is a zero.
  - `totals` (SeriesTotalsEntity, required): The window the buckets cover.
  - `previous` (SeriesWindowEntity, required): The window of the same length just before it, for growth.
  - `swaps` (SeriesSwapsEntity, required): Swaps of every kind (Stellar DEX, Solana and Monad, cross-chain, USDT0 sent through LayerZero) on the network the key targets: a sandbox key counts no Solana, Monad, cross-chain swap or USDT0 transfer, which run on mainnet only.
  - `liquidity` (SeriesLiquidityEntity, required): Liquidity pool operations on the network the key targets.
  - `webhooks` (SeriesWebhooksEntity, required): Webhook deliveries to the consumer’s endpoints.
  - `zkPayments` (SeriesPrivatePaymentsEntity, required): Private payments (amounts hidden on-chain, /v1/zk-payments) on the network the key targets. They run on testnet only for now, so a production key counts none.
- `400`: ValidationFailed (see Shared responses)
- `401`: Unauthorized (see Shared responses)
- `403`: Forbidden (see Shared responses)
- `500`: InternalError (see Shared responses)

## Settled (and pending) amount per asset

`GET /v1/balances`

Per chain and asset, what this consumer's payment intents settled (`amount`, with their `count`) and what is still `PENDING` or `SUBMITTED` (`pending`), on the API key’s network only (mainnet for a production key, testnet for a test key). Largest settled amount first, as `{ data, total }` with no paging. Reused per consumer and network for a few seconds (10 by default), so a new payment can take that long to show.

Requires the `payments:read` scope.

**Responses**

- `200` (`AnalyticsBalancesEntity`): OK
  - `data` (AssetBalanceEntity[], required): One entry per chain and asset, largest settled amount first.
  - `total` (number, required): Number of entries in `data` (the list is not paged).
- `401`: Unauthorized (see Shared responses)
- `403`: Forbidden (see Shared responses)
- `500`: InternalError (see Shared responses)

## Recent API requests reaching the service (with details)

`GET /v1/logs`

This consumer's requests, newest first, with method, path, status code, duration, client IP and user agent; the dashboard’s own console calls are left out. `status` is `ok` below 400, `pending` for a 4xx and `fail` for a 5xx. Paged with `take` (default and maximum 100) and `skip`; answers `{ data, total, take, skip }`, never cached.

Requires the `payments:read` scope.

**Query parameters**

- `take` (number, optional): Page size: how many items to return (1 to 100).
- `skip` (number, optional): How many items to skip before this page (offset).

**Responses**

- `200` (`ApiLogListEntity`): OK
  - `data` (ApiLogEntity[], required): The requests of this page, newest first.
  - `total` (number, required): Total matching rows, not the page length.
  - `take` (number, required): The page size applied (the `take` query parameter).
  - `skip` (number, required): Rows skipped before this page (the `skip` query parameter).
- `400`: ValidationFailed (see Shared responses)
- `401`: Unauthorized (see Shared responses)
- `403`: Forbidden (see Shared responses)
- `500`: InternalError (see Shared responses)

## Recent webhook deliveries across all endpoints (with details)

`GET /v1/logs/webhooks`

Deliveries to every webhook endpoint of this consumer, newest first: the endpoint and its `url`, `eventType`, `eventId`, `attempts`, the last `responseStatus` and `error`, and `status` (`ok` when delivered, `fail` when failed, `pending` otherwise). The payload is never included. Paged with `take` (default and maximum 100) and `skip`; answers `{ data, total, take, skip }`, never cached.

Requires the `webhooks:read` scope.

**Query parameters**

- `take` (number, optional): Page size: how many items to return (1 to 100).
- `skip` (number, optional): How many items to skip before this page (offset).

**Responses**

- `200` (`WebhookLogListEntity`): OK
  - `data` (WebhookLogEntity[], required): The deliveries of this page, newest created first.
  - `total` (number, required): Total matching rows, not the page length.
  - `take` (number, required): The page size applied (the `take` query parameter).
  - `skip` (number, required): Rows skipped before this page (the `skip` query parameter).
- `400`: ValidationFailed (see Shared responses)
- `401`: Unauthorized (see Shared responses)
- `403`: Forbidden (see Shared responses)
- `500`: InternalError (see Shared responses)

## Shared responses

- **Unauthorized** (`ApiErrorBodyEntity`): `no_authenticated_consumer`: The gateway forwarded no API key identity
  - `statusCode` (number, required): Always the HTTP status of the response itself.
  - `code` (string, required): Stable machine-readable code. Branch on this, never on the message: messages are human-facing and may be reworded; codes are never renamed once published. Each response documents the subset it can return. One of: `insufficient_scope`, `no_authenticated_consumer`, `gateway_required`, `admin_console_only`, `not_found`, `validation_failed`, `payload_too_large`, `idempotency_conflict`, `operation_in_flight`, `invalid_state_transition`, `slippage_exceeded`, `insufficient_balance`, `no_path_found`, `trustline_missing`, `invalid_amount`, `invalid_memo`, `transaction_rejected`, `transaction_already_settled`, `recipient_not_registered`, `payment_transfer_mismatch`, `fee_transfer_mismatch`, `merchant_fee_transfer_mismatch`, `payer_mismatch`, `transaction_not_found`, `expired`, `network_unsupported`, `asset_unsupported`, `merchant_fee_unsupported`, `provider_error`, `provider_unavailable`, `quote_not_found`, `quote_expired`, `kyc_state_invalid`, `kyc_review_required`, `account_disabled`, `payload_expired`, `rate_limited`, `customer_wallet_taken`, `alias_taken`, `alias_name_invalid`, `alias_challenge_invalid`, `alias_signature_invalid`, `alias_recovery_invalid`, `alias_address_conflict`, `wallet_handshake_invalid`, `wallet_verifier_invalid`, `wallet_login_code_invalid`, `wallet_login_code_cooldown`, `wallet_session_invalid`, `wallet_signature_invalid`, `wallet_backup_invalid`, `wallet_backup_limit`, `wallet_account_mismatch`, `wallet_provider_unavailable`, `wallet_return_url_not_allowed`, `wallet_recovery_setup_refused`, `easy_recovery_not_found`, `easy_recovery_already_offered`, `easy_recovery_not_offered`, `easy_recovery_code_invalid`, `easy_recovery_burned`, `plugin_not_installed`, `plugin_consent_mismatch`, `plugin_rejected`, `plugin_quota_exceeded`, `plugin_failed`, `protected_payment_buyer_mismatch`, `protected_payment_signature_invalid`, `misconfigured`, `internal_error`.
  - `error` (string, required): The HTTP reason phrase for `statusCode`.
  - `message` (string | string[], required): Human-readable detail. An array when class-validator rejected the body.
  - `details` (object, optional): Machine-readable facts about this failure, present only on the codes whose example shows it: `easy_recovery_code_invalid` carries `{ "attemptsLeft": 4 }`. Absent everywhere else.
  - `path` (string, required): The path of the request that failed.
  - `timestamp` (string, required): When the envelope was produced, ISO 8601.
- **Forbidden** (`ApiErrorBodyEntity`): `insufficient_scope`: the API key does not hold the scope this route requires. The shared public API key also gets this on every route that is not marked `x-cosmos-public-key`, with a message saying so; more scopes will not help, the key is the wrong one. `gateway_required`: the request did not arrive through APISIX.
- **InternalError** (`ApiErrorBodyEntity`): Unexpected server error. The detail is logged server-side and never returned: there is nothing in the body to branch on beyond the code.
- **ValidationFailed** (`ApiErrorBodyEntity`): The body, query or path failed validation. `message` is an array of the individual failures. Routes that reject a *valid* request for a reason of their own (an amount, a memo, a state) document the code for it on their own 400.
