Account & Settings

Read-only API

Read-only API

Metricgram includes a basic read-only API so external tools can query group data without accessing your dashboard.

Beta: The API is currently in testing and is available from the Pro plan and above.

Create an API token

  1. Go to Settings in your Metricgram dashboard.
  2. Open the API tokens section.
  3. Choose the group that the token should access.
  4. Click Create token.
  5. Copy the token immediately. It is only shown once.

Each token is linked to one group. For now, you can have one active token per group, and you can revoke it at any time.

Authentication

Send the token as a Bearer token in the Authorization header:

curl -H "Authorization: Bearer YOUR_API_TOKEN" \
  "https://metricgram.com/api/v1/members"

Successful responses are returned in JSON format.

Rate limit

Each token is limited to 60 requests per hour. When the limit is reached, the API returns 429 rate_limited.

GET /api/v1/members

Returns the members of the group linked to the token.

Supported parameters:

  • status: all, active, inactive, left, or unbaned
  • admin: true or false
  • is_bot: true or false. This parameter only filters boolean values; unknown values (null) are returned only when this filter is not used.
  • query: search by Telegram ID, username, or first name
  • limit: default 100, maximum 500
  • page: default 1
  • include_email: true or false. Default: false. When true, Metricgram uses the subscriber email first, then the email stored on the group member record. It can be null.

Example:

curl -G "https://metricgram.com/api/v1/members" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  --data-urlencode "status=active" \
  --data-urlencode "limit=100" \
  --data-urlencode "include_email=true" \
  --data-urlencode "page=1"

Example JSON response:

{
  "data": [
    {
      "telegram_id": "123456789",
      "username": "ana",
      "first_name": "Ana",
      "language_code": "es",
      "is_bot": false,
      "status": "active",
      "joined_at": "2026-04-10T12:30:00Z",
      "admin": false,
      "email": "ana@example.com"
    }
  ],
  "meta": {
    "group_id": 42,
    "group_title": "My group",
    "page": 1,
    "limit": 100,
    "count": 1,
    "has_more": false,
    "filters": {
      "status": "active"
    }
  }
}

Main response fields:

  • telegram_id: Telegram ID as text. It can be null if Metricgram does not have it stored.
  • username, first_name, and language_code: public Telegram data. They can be null.
  • is_bot: true, false, or null when Telegram has not provided that value.
  • status: active, inactive, left, unbaned, or null if no status is stored.
  • admin: true or false.
  • joined_at: join date in ISO 8601 format, or null.
  • email: only returned when include_email=true. Metricgram uses the subscriber email first, then the email stored on the group member record. It can be null.
  • meta: pagination and filter data for the request.

GET /api/v1/active_users

Returns non-admin members with messages or reactions recorded in the selected date range. The group owner is excluded from this list. Results are sorted by descending activity: first by activity_count, then by last_activity_at.

Supported parameters:

  • start_date: start date in YYYY-MM-DD format. Default: 30 days ago.
  • end_date: end date in YYYY-MM-DD format. Default: today.
  • limit: default 100, maximum 500
  • page: default 1
  • include_email: true or false. Default: false. When true, Metricgram uses the subscriber email first, then the email stored on the group member record. It can be null.

Example:

curl -G "https://metricgram.com/api/v1/active_users" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  --data-urlencode "start_date=2026-04-01" \
  --data-urlencode "end_date=2026-04-30" \
  --data-urlencode "limit=100" \
  --data-urlencode "include_email=true" \
  --data-urlencode "page=1"

Example JSON response:

{
  "data": [
    {
      "telegram_id": "123456789",
      "username": "ana",
      "first_name": "Ana",
      "language_code": "es",
      "is_bot": null,
      "member_status": "active",
      "admin": false,
      "joined_at": "2026-04-10T12:30:00Z",
      "email": "ana@example.com",
      "message_count": 18,
      "reaction_count": 4,
      "activity_count": 22,
      "last_message_at": "2026-04-30T19:15:00Z",
      "last_reaction_at": null,
      "last_activity_at": "2026-04-30T19:15:00Z"
    }
  ],
  "meta": {
    "group_id": 42,
    "group_title": "My group",
    "start_date": "2026-04-01",
    "end_date": "2026-04-30",
    "page": 1,
    "limit": 100,
    "count": 1,
    "has_more": false
  }
}

Main response fields:

  • telegram_id: Telegram ID as text. It can be null if Metricgram does not have it stored.
  • username, first_name, and language_code: public Telegram data. They can be null.
  • is_bot: true, false, or null when Telegram has not provided that value.
  • member_status: same text values as status in /api/v1/members; it can be null if no status is stored.
  • admin: true or false; in this endpoint it is normally false because admins are excluded.
  • joined_at: join date in ISO 8601 format, or null.
  • email: only returned when include_email=true. Metricgram uses the subscriber email first, then the email stored on the group member record. It can be null.
  • message_count, reaction_count, and activity_count: integer counters calculated only within the selected date range, not the user's full history. activity_count is message_count + reaction_count.
  • last_message_at and last_reaction_at: ISO 8601 datetime, or null when there was no activity of that type.
  • last_activity_at: ISO 8601 datetime for the latest recorded activity.
  • meta: group, date range, and pagination data for the request.

GET /api/v1/subscriber_health

Returns the same data as the Subscriber health panel: active linked subscribers, recent activity, risk signals, upcoming renewals, and plan breakdown.

By default it uses the same windows as the panel: 30 days for activity and 14 days for upcoming renewals. If you change these parameters, the results may not exactly match the panel.

Supported parameters:

  • activity_days: number of days for recent activity. Default 30, maximum 365; values above 365 are capped to 365.
  • renewal_days: number of days for upcoming renewals. Default 14, maximum 90; values above 90 are capped to 90.
  • include_email: true or false. Default: false. When true, at-risk subscribers include the email stored on the subscription. It can be null.

Example:

curl -G "https://metricgram.com/api/v1/subscriber_health" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  --data-urlencode "activity_days=30" \
  --data-urlencode "renewal_days=14" \
  --data-urlencode "include_email=true"

Example JSON response:

{
  "data": {
    "total_subscribers": 24,
    "activity_days": 30,
    "renewal_days": 14,
    "activity_range": { "start_date": "2026-04-01", "end_date": "2026-04-30" },
    "previous_activity_range": { "start_date": "2026-03-02", "end_date": "2026-03-31" },
    "compare_activity_drop": true,
    "metrics": {
      "engaged": { "count": 18, "percentage": 75 },
      "at_risk": { "count": 3, "percentage": 13 },
      "upcoming_renewals": { "count": 5, "percentage": 21 }
    },
    "at_risk_subscribers": [
      {
        "telegram_id": "123456789",
        "username": "ana",
        "first_name": "Ana",
        "language_code": "es",
        "is_bot": false,
        "plan_lines": ["Pro monthly", "29 EUR / month"],
        "subscribed_until": "2026-05-08T10:00:00Z",
        "subscription_attention": "renews_on",
        "subscription_attention_days": 2,
        "risk_indicators": ["activity_drop"],
        "risk_score": 1,
        "risk_level": "low",
        "current_message_count": 2,
        "current_reaction_count": 0,
        "current_activity_count": 2,
        "previous_message_count": 12,
        "previous_reaction_count": 1,
        "previous_activity_count": 13,
        "email": "ana@example.com"
      }
    ],
    "plan_rows": [
      {
        "plan_lines": ["Pro monthly", "29 EUR / month"],
        "active_count": 12,
        "engaged_count": 9,
        "at_risk_count": 2,
        "engaged_percentage": 75,
        "at_risk_percentage": 17
      }
    ]
  },
  "meta": {
    "group_id": 42,
    "group_title": "My group"
  }
}

Main fields:

  • total_subscribers: active linked subscribers included in the calculation.
  • activity_range / previous_activity_range: current and previous activity windows.
  • metrics: summary counters and percentages.
  • at_risk_subscribers: subscribers with risk signals; risk_indicators can be no_activity, activity_drop, or canceled; risk_level can be low, medium, or high.
  • plan_rows: active linked subscribers grouped by subscription plan.
  • email: only returned inside at_risk_subscribers when include_email=true.

Common errors

  • 401 unauthorized: the token is missing or invalid.
  • 403 forbidden: the token does not have permission or the group is not available for the account.
  • 400 invalid_date_range: the date range is invalid.
  • 429 rate_limited: the hourly limit has been reached.

Was this article helpful?

Manage your Telegram group smarter