/entitlements/grants - Grants report with filters

Add MCP server to your AI tool

Allow AI tools and LLMs to interact with the API documentation portal through MCP.

MCP server URL

https://api.my.nethesis.it/mcp

Standard setup for AI tools providing an mcp.json file

mcp.json
{
  "my.nethesis.it MCP server": {
    "url": "https://api.my.nethesis.it/mcp"
  }
}

Close
GET /entitlements/grants

Paginated grants report. The owner organization and Super Admins see the whole fleet; other users only the grants of systems in their hierarchy.

Query parameters

  • entitlement string

    Filter by catalog id

  • organization_id string

    Filter by the organization owning the system

  • source string

    Filter by grant source

    Values are manual, shop, or legacy-import.

  • active string

    When "true", only active grants (not revoked, not expired)

    Value is true.

  • expiring_before string(date-time)

    Only grants expiring before this RFC3339 timestamp

  • page integer

    Page number

    Default value is 1.

  • page_size integer

    Page size (max 200)

    Maximum value is 200. Default value is 50.

Responses

  • 200 application/json

    Grants retrieved successfully

    Hide response attributes Show response attributes object
    • code integer
    • message string
    • data object
      Hide data attributes Show data attributes object
      • grants array[object]

        One row of the grants report — the grant plus the identity of the system it belongs to

        Hide grants attributes Show grants attributes object

        One row of the grants report — the grant plus the identity of the system it belongs to

        • id string(uuid)

          Grant ID

        • system_id string

          ID of the system the grant belongs to

        • entitlement string

          Catalog id of the granted add-on

        • scope string

          Application instance the grant is narrowed to (only for scoped catalog items). Omitted = whole system.

        • source string

          How the grant was created

          Values are manual, shop, or legacy-import.

        • source_ref string

          Free-form reference to the originating record (e.g. shop subscription id)

        • valid_from string(date-time)

          When the grant became valid

        • valid_until string(date-time) | null

          Expiry of the grant. Null = perpetual.

        • revoked_at string(date-time) | null

          When the grant was revoked. Null = not revoked.

        • revoked_source string

          Who revoked the grant: manual (admin via API/UI — deliberate, the shop button is not offered again) or shop (deactivate webhook: subscription cancelled or payment failed — buyable again). Omitted when not revoked.

          Values are manual or shop.

        • active boolean

          Derived: not revoked and not expired

        • pending_ref string

          Shop order placed at checkout and not yet paid (display-only; cleared by activate or cancel). Omitted when nothing is pending.

        • pending_since string(date-time) | null

          When the pending order was placed

        • status string

          Server-computed lifecycle status. suspended = the grant is intact but the owning system (or its organization) is suspended or deleted, so collect rejects its credentials. pending = an order is awaiting payment (masks revoked/expired but never an active grant). Enforcement authorizes only truly active grants.

          Values are active, expired, revoked, suspended, or pending.

        • created_by object

          Snapshot of the user who created the grant or availability rule

          Hide created_by attributes Show created_by attributes object
          • user_id string

            Logto ID of the creator

          • user_name string

            Full name of the creator

          • organization_id string

            Organization ID of the creator

          • organization_name string

            Organization name of the creator

          • channel string

            Set to "shop" when the grant was created via POST /entitlements/activate. Omitted otherwise.

        • purchased_by object

          Audit snapshot of the my user that BOUGHT the grant on the shop, resolved from the order's customer email (webhook activation, or the legacy-import backfill when the expiry map carries the order email) and frozen at purchase time (robust to later renames/moves). Omitted for manual grants and legacy rows without an order. When the email matches no my user only email is present. When the buyer's organization is outside the viewer's hierarchy the snapshot is redacted to {out_of_scope: true} (owner org and Super Admin always see it in full).

          Hide purchased_by attributes Show purchased_by attributes object
          • logto_id string

            Logto ID of the buyer

          • name string

            Full name of the buyer at purchase time

          • email string

            Email of the buyer (the shop order's customer)

          • organization_id string

            Logto ID of the buyer's organization at purchase time

          • organization_name string

            Name of the buyer's organization at purchase time

          • org_role string

            Hierarchy role of the buyer's organization at purchase time

          • user_roles array[string]

            User role names of the buyer at purchase time

          • out_of_scope boolean

            Present (true) when the buyer identity was redacted because it is outside the viewer's hierarchy

        • variant object

          Shop variation (tier) of the purchased product line. Display metadata only: the add-on↔product mapping stays on the parent product and /auth enforcement ignores it. Refreshed by activate, so tier upgrades/downgrades follow the renewals. Omitted for manual grants and simple (non-variable) products.

          Hide variant attributes Show variant attributes object
          • id integer

            WooCommerce variation id

          • sku string

            SKU of the variation

          • label string

            Human-readable tier, from the variation attributes

        • renewal_count integer

          Paid shop orders on this grant beyond the first: activate increments it when source_ref changes (webhook retries on the same order never double-count). 0 = first period.

        • created_at string(date-time)
        • updated_at string(date-time)
        • system_name string

          Name of the system

        • system_key string

          Key of the system

        • organization_id string

          Logto ID of the organization owning the system

        • organization_name string

          Name of the organization owning the system

      • total integer
      • page integer
      • page_size integer
  • 400 application/json

    expiring_before is not a valid RFC3339 timestamp

    Hide response attributes Show response attributes object
    • code integer

      HTTP error code

    • message string

      Error message

    • data object
      Hide data attributes Show data attributes object
      • type string

        Type of error

        Values are validation_error or external_api_error.

      • errors array[object]
        Hide errors attributes Show errors attributes object
        • key string

          Field name that failed validation

        • message string

          Error code or message

        • value string

          Value that failed validation

      • details

        Additional error details

  • 401 application/json

    Unauthorized - invalid or missing token

    Hide response attributes Show response attributes object
    • code integer
    • message string
    • data object | null
  • 403 application/json

    Forbidden - insufficient permissions

    Hide response attributes Show response attributes object
    • code integer
    • message string
    • data object | null
  • 500 application/json

    Internal server error

    Hide response attributes Show response attributes object
    • code integer
    • message string
    • data object | null
GET /entitlements/grants
curl \
 --request GET 'https://api.your-domain.com/api/entitlements/grants' \
 --header "Authorization: Bearer $ACCESS_TOKEN"
Response examples (200)
{
  "code": 200,
  "message": "grants retrieved successfully",
  "data": {
    "grants": [
      {
        "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
        "system_id": "550e8400-e29b-41d4-a716-446655440000",
        "entitlement": "nsec-blacklist",
        "scope": "nethvoice1",
        "source": "manual",
        "source_ref": "sub_12345",
        "valid_from": "2026-07-01T10:00:00Z",
        "valid_until": "2027-07-01T10:00:00Z",
        "revoked_at": "2026-05-04T09:42:00Z",
        "revoked_source": "shop",
        "active": true,
        "pending_ref": "wc-order-83164",
        "pending_since": "2026-07-15T18:00:00Z",
        "status": "active",
        "created_by": {
          "user_id": "53h5zxpwu4vc",
          "user_name": "Edoardo Super",
          "organization_id": "lbswt1rxdhbz",
          "organization_name": "Nethesis Italia",
          "channel": "shop"
        },
        "purchased_by": {
          "logto_id": "53h5zxpwu4vc",
          "name": "Mario Rossi",
          "email": "mario.rossi@example.com",
          "organization_id": "akkbs6x2wo82",
          "organization_name": "ACME S.r.l.",
          "org_role": "reseller",
          "user_roles": [
            "Admin"
          ],
          "out_of_scope": true
        },
        "variant": {
          "id": 245,
          "sku": "ATS-15",
          "label": "1-15 device"
        },
        "renewal_count": 3,
        "created_at": "2026-07-01T10:00:00Z",
        "updated_at": "2026-07-01T10:00:00Z",
        "system_name": "Milan Office Firewall",
        "system_key": "NETH-F5D2-5E69-A174-45A9-B1AB-2BB9-03F5-F1B4",
        "organization_id": "akkbs6x2wo82",
        "organization_name": "ACME S.r.l."
      }
    ],
    "total": 42,
    "page": 1,
    "page_size": 50
  }
}
Response examples (400)
{
  "code": 400,
  "message": "validation failed",
  "data": {
    "type": "validation_error",
    "errors": [
      {
        "key": "username",
        "message": "required",
        "value": "string"
      }
    ]
  }
}
Response examples (401)
{
  "code": 401,
  "message": "invalid token",
  "data": {}
}
Response examples (403)
{
  "code": 403,
  "message": "insufficient permissions",
  "data": {}
}
Response examples (500)
{
  "code": 500,
  "message": "internal server error",
  "data": {}
}