/entitlements/deactivate - Shop-facing revocation of an add-on

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
POST /entitlements/deactivate

Revoke a shop-managed grant when the subscription is cancelled or expires (called by the NethShop webhook). Same addressing and auth as POST /entitlements/activate (manage:entitlements permission). The revocation is soft and idempotent.

When source_ref is provided it is matched against the grant: a PENDING activation with the same ref is cleared instead of revoked (order cancelled before payment), and a grant whose source_ref differs is left untouched — cancelling an old order can never revoke an entitlement another order paid for.

application/json

Body Required

  • system_key string Required

    Key of the system to revoke the add-on from

  • entitlement string Required

    Canonical catalog id or legacy alias of the add-on

  • scope string

    Application instance the grant is narrowed to

  • source_ref string

    Free-form reference to the originating record. When set, it is matched against the grant — a pending activation with the same ref is cleared instead of revoked, and a grant owned by a different ref is left untouched.

Responses

  • 200 application/json

    Entitlement deactivated successfully

    Hide response attributes Show response attributes object
    • code integer
    • message string
    • data object

      One add-on grant for one system, optionally narrowed to a single application instance via scope (omitted = whole system). active is derived: not revoked and not expired (valid_until null = perpetual). Revocation is soft (sets revoked_at, the row is kept for audit).

      Hide data attributes Show data attributes object
      • 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)
  • 400 application/json

    Unknown entitlement

    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
  • 404 application/json

    System not found for this key, or no grant for this (entitlement, scope)

    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

  • 500 application/json

    Internal server error

    Hide response attributes Show response attributes object
    • code integer
    • message string
    • data object | null
POST /entitlements/deactivate
curl \
 --request POST 'https://api.your-domain.com/api/entitlements/deactivate' \
 --header "Authorization: Bearer $ACCESS_TOKEN" \
 --header "Content-Type: application/json" \
 --data '{"system_key":"NETH-F5D2-5E69-A174-45A9-B1AB-2BB9-03F5-F1B4","entitlement":"nsec-blacklist","scope":"nethvoice1","source_ref":"sub_12345"}'
Request examples
{
  "system_key": "NETH-F5D2-5E69-A174-45A9-B1AB-2BB9-03F5-F1B4",
  "entitlement": "nsec-blacklist",
  "scope": "nethvoice1",
  "source_ref": "sub_12345"
}
Response examples (200)
{
  "code": 200,
  "message": "entitlement deactivated successfully",
  "data": {
    "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"
  }
}
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 (404)
{
  "code": 400,
  "message": "validation failed",
  "data": {
    "type": "validation_error",
    "errors": [
      {
        "key": "username",
        "message": "required",
        "value": "string"
      }
    ]
  }
}
Response examples (500)
{
  "code": 500,
  "message": "internal server error",
  "data": {}
}