> ## Documentation Index
> Fetch the complete documentation index at: https://neverminedag-sync-api-errors-9d14109.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Check Your Revenue (Seller)

> Have an AI agent pull a revenue report for the agents and plans you sell on Nevermined — total revenue, MRR, active subscribers, and credits consumed per plan.

If you sell agents or plans, this flow turns "how's it going?" into a report an agent generates on demand: revenue per agent, monthly recurring revenue, active subscribers, and how many credits buyers are burning. The aggregated numbers come from your organization's analytics; if you're not on a Premium tier, the agent falls back to the always-available building blocks.

## Useful for

* A **revenue snapshot** — total earnings per agent over any date range.
* Tracking **MRR and active subscribers** to see growth at a glance.
* Seeing **which plans get used** (credits burned, unique users) so you can price and iterate.

## Try it yourself

```text theme={null}
You are my autonomous payments agent. Using the Nevermined `nevermined-payments` skill (https://github.com/nevermined-io/docs/tree/main/skills/nevermined-payments) (Track A, A7 + references/seller-operations.md) and my NVM_API_KEY, produce a revenue report for the AI agents and plans I sell on Nevermined sandbox. Base URL: https://api.sandbox.nevermined.app/api/v1 . Send `Authorization: Bearer $NVM_API_KEY` on every call. Never print, echo, or persist the key.

STEP 1 — Inventory + discover my org id (always do this first; it never needs Premium):
- GET /protocol/plans?page=1&offset=50 and GET /protocol/agents?page=1&offset=50.
- These return { total, page, offset, plans|agents: [ <full record> ] }. For each item read:
    name        = metadata.main.name
    price       = SUM of registry.price.amounts  (each is a STRING in 6-decimal token units; the array splits across builder + a platform-fee receiver — contract-default 1% for crypto, 2% for fiat, and an org-level crypto fee can add a third receiver — so always SUM the array, never read index 0; then divide by 1,000,000 for USD/USDC; e.g. fiat ["9800000","200000"] => 10000000 = $10.00)
    paymentType = registry.price.isCrypto ? "crypto (USDC/EURC)" : "fiat (card)"
    credits     = registry.credits.amount ; durationSecs (0 = non-expiring fixed credits; >0 = time-based)
    org id      = item.orgId  and  item.organizationName   <-- this is how you discover my org id
- Summarize every plan and agent: name, type, price, credits, owning org. This summary is the baseline report and must always be produced.
- Pick MY_ORG_ID = the most common non-null .orgId across my plans/agents. If none is non-null, skip STEP 2 entirely and report "no org-level analytics available; inventory only".

STEP 2 — Org analytics enrichment (only if MY_ORG_ID matches ^org-[0-9a-f-]+$):
Call, with from/to spanning the last 90 days (from = today-90d, to = today, ISO-8601 Z):
  GET /organizations/{MY_ORG_ID}/analytics/revenue?from=&to=
  GET /organizations/{MY_ORG_ID}/analytics/mrr
  GET /organizations/{MY_ORG_ID}/analytics/usage?from=&to=
  GET /organizations/{MY_ORG_ID}/analytics/customers?limit=50
Treat analytics as VALID only if you get HTTP 200 AND a validly-shaped org id was used. Note these real failure modes and fall back to the STEP 1 inventory summary if any occur:
  - 403 BCK.AUTH.0004 ("Organisation admin privileges required") — the org isn't mine / not Premium-admin. (The skill mentions BCK.ORGANIZATIONS.0022; the live code may instead return BCK.AUTH.0004 — treat any 403 the same.)
  - A 200 response that is all zeros/empty ({"mrr":"0"}, totalRevenue "0", items []) while STEP 1 shows I have published plans — this is the silent failure you get from a bad/placeholder org id. Do NOT report it as real; fall back.
Report from the analytics data:
  1. Revenue per row (the API labels rows agentId/agentName but actually groups by PLAN — report them as plans/offerings), last 90 days, plus the grand total. Convert all *Revenue/*Spent integer strings to USD by dividing by 1,000,000.
  2. MRR and active subscribers (mrr, activeSubscriptions). Note that MRR can legitimately be 0 if my sales were one-off credit purchases rather than recurring subscriptions.
  3. Credits consumed per plan with unique users (creditsBurned, uniqueUsers).

Output: the inventory summary (always), then the analytics numbers if STEP 2 succeeded, clearly stating which path produced the figures and the exact date window used.
```

## How it works

There are two layers: aggregated **organization analytics** (Premium tier) and always-available **building blocks**.

<Steps>
  <Step title="Organization analytics (Premium tier)">
    Set the analytics base once, then pull each metric (`from`/`to` are ISO-8601; `from` inclusive, `to` exclusive):

    ```bash theme={null}
    B="{API_BASE}/organizations/<ORG_ID>/analytics"

    # Revenue per agent
    curl -s -H "Authorization: Bearer $NVM_API_KEY" "$B/revenue?from=2026-03-20T00:00:00Z&to=2026-06-18T00:00:00Z"
    # → { items: [ { agentId, agentName, totalRevenue, transactionCount } ], totalRevenue }

    # MRR + active subscribers
    curl -s -H "Authorization: Bearer $NVM_API_KEY" "$B/mrr"
    # → { mrr, activeSubscriptions }

    # Credits burned per plan
    curl -s -H "Authorization: Bearer $NVM_API_KEY" "$B/usage?from=...&to=..."
    # → { items: [ { planId, planName, creditsBurned, uniqueUsers } ] }
    ```

    **Discover your `orgId` from the records themselves** — every item in `GET /protocol/plans` and `/protocol/agents` carries `.orgId` and `.organizationName`; take the most common non-null `.orgId` across your published items (no separate lookup endpoint exists). Only call analytics if it matches `^org-[0-9a-f-]+$`. Three failure modes to handle:

    * A **foreign / non-admin** org returns `403 BCK.AUTH.0004` ("Organisation admin privileges required").
    * A **non-Premium** org returns `403 BCK.ORGANIZATIONS.0022`.
    * A **malformed or placeholder** org id (e.g. an unsubstituted `<ORG_ID>`) returns a **silent `200` of all-zeros** — never report that as real revenue. Validate the id shape first, and treat a zero result while you *have* published plans as a failure: fall back to the building blocks below.

    <Note>
      The `revenue`/`usage` rows are labelled `agentId`/`agentName` but are actually grouped **by plan**. Money fields like `totalRevenue` are stringified integers in 6-decimal token units — divide by 1,000,000 for USD. (`creditsBurned` is a plain credit count, not money.)
    </Note>
  </Step>

  <Step title="Building blocks (any tier)">
    These need no Premium and no `orgId` — they're scoped to your API key:

    ```http theme={null}
    GET {API_BASE}/protocol/plans
    GET {API_BASE}/protocol/agents
    Authorization: Bearer <api-key>
    ```

    Each returns `{ total, page, offset, plans|agents: [ … ] }` where every item is the full record — read the name from `metadata.main.name` and the id from `id`. Combine with per-holder balances (`GET /protocol/plans/{planId}/balance/{address}`) to approximate usage when analytics aren't available.
  </Step>

  <Step title="Per-request usage (optional)">
    For token-level usage and cost tracking, the SDK integrates with Helicone via `payments.observability`. See [AI Agents Observability](/docs/solutions/ai-agents-observability) for the full picture.
  </Step>
</Steps>

## Related

<CardGroup cols={2}>
  <Card title="Register a plan & agent" icon="store" href="/docs/agents-guide/register-plan-and-agent">
    Publish the agents and plans this report measures.
  </Card>

  <Card title="AI Agents Observability" icon="chart-line" href="/docs/solutions/ai-agents-observability">
    Usage, cost, and performance tracking for your agents.
  </Card>

  <Card title="Add payments to your agent" icon="plug" href="/docs/agents-guide/add-payments">
    Start charging so there's revenue to report.
  </Card>
</CardGroup>
