Managing User Entitlements

Administrative APIs for managing user entitlements

A user's entitlements can be modified either by applying an entitlements set to the user or by explicitly applying individual entitlements to the user.

Common Entitlements Types

# An entitlement
type Entitlement {
  # Name of the entitlement
  name: String!

  # Optional description of the entitlement
  description: String

  # Value of the entitlement. Type Float to allow for values
  # values larger than possible with Int. Value is a
  # positive integer.
  value: Float!
}

# Sub-resource consumer of the entitlement
# For example some entitlements are per-Sudo
type EntitlementConsumer {
  # ID of the consuming resource
  id: ID!

  # Issuer of the consuming resource ID e.g. sudoplatform.sudoservice for Sudos
  issuer: String!
}

# Effective entitlements for an external user
type ExternalUserEntitlements  {
  # Time of initial creation of user entitlements mapping in milliseconds
  # since epoch. Number is integral, float type provides sufficient
  # precision.
  createdAtEpochMs: Float!

  # Time of last updates of user entitlements mapping in milliseconds
  # since epoch. Number is integral, float type provides sufficient
  # precision.
  updatedAtEpochMs: Float!

  # Version number of the user's entitlements. This is incremented every
  # time there is a change of entitlements set or explicit entitlements
  # for this user.
  #
  # For users entitled by entitlement set, the fractional part of this version
  # specifies the version of the entitlements set itself. Entitlements set version
  # is divided by 100000 then added to the user entitlements version
  #
  # This ensures that the version of user entitlements always increases mon
  version: Float!

  # External IDP identifier identifying the user
  externalId: String!

  # Sudo Platform owner. This value matches the subject in identity
  # tokens used to authenticate to Sudo Platform services.
  owner: String

  # Name of the entitlements set specified for this user. Will be undefined
  # if entitlements have been specified explicitly rather than by an
  # entitlements set name.
  entitlementsSetName: String

  # Effective entitlements for the user either obtained from the entitlements
  # set or as specified explicitly for this user.
  entitlements: [Entitlement!]!
}

# An error result returned for an operation in a bulk applyEntitlements*ToUsers
# mutation.
type ExternalUserEntitlementsError {
  # Error code of failed operation
  error: String!
}

# Union of success and error results returned for operations in a bulk
# applyEntitlements*ToUsers mutation.
union ExternalUserEntitlementsResult =
    ExternalUserEntitlements
  | ExternalUserEntitlementsError

Apply Entitlements Set to a User

A previously defined entitlements set can be applied to a user by calling the applyEntitlementsSetToUser mutation.

# Input for the applyEntitlementsSetToUser mutation
input ApplyEntitlementsSetToUserInput {
  externalId: String!
  entitlementsSetName: String!
}


# Apply an entitlement set with the specified name to a user.
applyEntitlementsSetToUser(
    input: ApplyEntitlementsSetToUserInput!
): ExternalUserEntitlements!

Possible Errors

  • EntitlementsSetNotFoundError will be returned if an entitlements set with the name of the supplied entitlementsSetName parameter is unknown to the entitlements service.

  • AlreadyUpdatedError will be returned if an attempt to update a user's entitlements is made after the user's entitlements have already been updated to a later version.

  • ServiceError will be returned for internal errors.

Applying an entitlements set to a user using SDK.

do {
    let userEntitlements = try await client.applyEntitlementsSetToUserWithExternalId(
        externalId: externalId,
        entitlementsSetName: "Premium user",
    )
} catch let error {
    // Handle error. An error may be thrown if the backend is unable perform
    // the operation due to invalid input, availability or security issues.
}

Apply Entitlements Sets to Multiple Users

Previously defined entitlements set can be applied to multiple users by calling the applyEntitlementsSetToUsers mutation.

# Input for the applyEntitlementsSetToUsers mutation
input ApplyEntitlementsSetToUsersInput {
  operations: [ApplyEntitlementsSetToUserInput!]!
}

# Apply entitlement sets to multiple users.
applyEntitlementsSetToUsers(
    input: ApplyEntitlementsSetToUsersInput!
): [ExternalUserEntitlementsResult!]!

Possible Errors

Each individual operation may fail with any of the same errors that applyEntitlementsSetToUser may fail. These are returned in the corresponding element of the returned list of results.

In addition, the overall mutation can fail with the following errors:

  • LimitExceededError will be returned if too many operations are specified. The maximum number of operations is 1500. This may be adjusted for specific environments.

  • BulkOperationDuplicateUsersError will be returned if more than one individual operation specifies the same value for externalId.

  • ServiceError will be returned for internal errors.

Applying an entitlements set to multiple users using SDK.

applyEntitlementsSetToUsers not currently available for Swift

Apply Entitlements Sequence to a User

A previously defined entitlements setquence can be applied to a user by calling the applyEntitlementsSequenceToUser mutation.

# Input for the applyEntitlementsSequenceToUser mutation
input ApplyEntitlementsSequenceToUserInput {
  externalId: String!
  entitlementsSequenceName: String!

  # Milliseconds since epoch from when user's transitions should
  # be calculated. Defaults to current time.
  # Is a Float only for precision. Must be an integral value.
  transitionsRelativeToEpochMs: Float
}


# Apply an entitlement sequence with the specified name to a user.
applyEntitlementsSequenceToUser(
    input: ApplyEntitlementsSequenceToUserInput!
): ExternalUserEntitlements!

Possible Errors

  • EntitlementsSequenceNotFoundError will be returned if an entitlements sequence with the name of the supplied entitlementsSequenceName parameter is unknown to the entitlements service.

  • AlreadyUpdatedError will be returned if an attempt to update a user's entitlements is made after the user's entitlements have already been updated to a later version.

  • ServiceError will be returned for internal errors.

Applying an entitlements sequence to a user using SDK.

do {
    let userEntitlements = try await client.applyEntitlementsSequenceToUserWithExternalId(
        externalId: externalId,
        entitlementsSequenceName: "premium_subscription_plan",
    )
} catch let error {
    // Handle error. An error may be thrown if the backend is unable perform
    // the operation due to invalid input, availability or security issues.
}

Apply Entitlements Sequences to Multiple Users

Previously defined entitlements sequences can be applied to multiple users by calling the applyEntitlementsSequenceToUsers mutation.

# Input for the applyEntitlementsSequenceToUsers mutation
input ApplyEntitlementsSequenceToUsersInput {
  operations: [ApplyEntitlementsSequenceToUserInput!]!
}

# Apply entitlement sequences to multiple users.
applyEntitlementsSequenceToUsers(
    input: ApplyEntitlementsSequenceToUsersInput!
): [ExternalUserEntitlementsResult!]!

Possible Errors

Each individual operation may fail with any of the same errors that applyEntitlementsSequenceToUser may fail. These are returned in the corresponding element of the returned list of results.

In addition, the overall mutation can fail with the following errors:

  • LimitExceededError will be returned if too many operations are specified. The maximum number of operations is 1500. This may be adjusted for specific environments.

  • BulkOperationDuplicateUsersError will be returned if more than one individual operation specifies the same value for externalId.

  • ServiceError will be returned for internal errors.

Applying an entitlements set to multiple users using SDK.

applyEntitlementsSequenceToUsers not currently available for Swift

Apply Entitlements to a User

A list of individual entitlements can be applied to a user by calling the applyEntitlementsToUser mutation.

# Input representing an entitlement
input EntitlementInput {
  # Name of the entitlement
  name: String!

  # Description, if any, of the entitlement as specified by the entitlements administrator.
  description: String

  # Value of the entitlement. Type Float to allow for values
  # values larger than possible with Int. Value is a
  # positive integer. Maximum value when setting entitlements is 2^52 - 1
  value: Float!
}

# Input for the applyEntitlementsToUser mutation
input ApplyEntitlementsToUserInput {
  externalId: String!
  entitlements: [EntitlementInput!]!
}

# Apply entitlements to a user without using a named entitlements set.
applyEntitlementsToUser(
  input: ApplyEntitlementsToUserInput!
): ExternalUserEntitlements!

Possible Errors

  • InvalidEntitlementsError will be returned if an entitlement name is not a recognized entitlement.

  • AlreadyUpdatedError will be returned if an attempt to update a user's entitlements is made after the user's entitlements have already been updated to a later version.

  • ServiceError will be returned for internal errors.

Applying entitlements to a user using SDK.

do {
    let userEntitlements = try await client.applyEntitlementsToUserWithExternalId(
        externalId: externalId,
        entitlements: [Entitlement(name: "sudoplatform.sudo.max", description: "Max. Sudos", value: 3)]
    ) 
} catch let error {
    // Handle error. An error may be thrown if the backend is unable perform
    // the operation due to invalid input, availability or security issues.
}

Apply Entitlements to Multiple Users

Entitlements can be applied to multiple users by calling the applyEntitlementsToUsers mutation.

# Input for the applyEntitlementsToUsers mutation
input ApplyEntitlementsToUsersInput {
  operations: [ApplyEntitlementsToUserInput!]!
}

# Apply entitlement to multiple users.
applyEntitlementsToUsers(
    input: ApplyEntitlementsToUsersInput!
): [ExternalUserEntitlementsResult!]!

Possible Errors

Each individual operation may fail with any of the same errors that applyEntitlementsToUser may fail. These are returned in the corresponding element of the returned list of results.

In addition, the overall mutation can fail with the following errors:

  • LimitExceededError will be returned if too many operations are specified. The maximum number of operations is 1500. This may be adjusted for specific environments.

  • BulkOperationDuplicateUsersError will be returned if more than one individual operation specifies the same value for externalId.

  • ServiceError will be returned for internal errors.

Applying an entitlements set to multiple users using SDK.

applyEntitlementsToUsers not currently available for Swift

Apply Expendable Entitlements to a User

A list of individual expendable entitlements can be applied to a user by calling the applyExpendableEntitlementsToUser mutation. The user's expendable entitlements will be incremented (or decremented if entitlement value is negaetive) by the amount specified for each entitlement. Since this is an increment operation, a request ID is required and is used to provide idempotence of the operation. Replayed requests will have no effect on the user's expendable entitlements the current user entitlements will be returned.

# Input representing an entitlement
input EntitlementInput {
  # Name of the entitlement
  name: String!

  # Description, if any, of the entitlement as specified by the entitlements administrator.
  description: String

  # Value of the entitlement. Type Float to allow for values
  # values larger than possible with Int. Value is a
  # positive integer. Maximum value when setting entitlements is 2^52 - 1
  value: Float!
}

# Input for the applyEntitlementsToUser mutation
input ApplyExpendableEntitlementsToUserInput {
  externalId: String!
  expendableEntitlements: [EntitlementInput!]!
  requestId: String!
}

# Apply expendable entitlements to a user.
applyExpendableEntitlementsToUser(
  input: ApplyExpendableEntitlementsToUserInput!
): ExternalUserEntitlements!

Possible Errors

  • InvalidEntitlementsError will be returned if an entitlement name is not a recognized expendable entitlement.

  • DuplicateEntitlementError will be returned if the same expendable entitlement is specified more than once in the expendableEntitlements property of the input.

  • NegativeEntitlementError will be returned if the change in an expendable entitlement would result in negative entitlement.

  • AlreadyUpdatedError will be returned if an attempt to update a user's entitlements is made after the user's entitlements have already been updated to a later version.

  • ServiceError will be returned for internal errors.

Applying entitlements to a user using SDK.

do {
    let userEntitlements = try await client.applyEntitlementsToUserWithExternalId(
        externalId: externalId,
        entitlements: [Entitlement(name: "sudoplatform.sudo.max", description: "Max. Sudos", value: 3)]
    ) 
} catch let error {
    // Handle error. An error may be thrown if the backend is unable perform
    // the operation due to invalid input, availability or security issues.
}

Get Entitlements for a User

The effective entitlements assigned to a user and their current consumption of those entitlements is retrieved by calling the getEntitlementsForUser query.

Entitlement values are returned with three pieces of information:

value is the total entitled amount

consumed is the amount of the entitlement consumed

available is the amount remaining.

It is always true that value = consumed + available

It's possible that available can be negative. This can happen transiently when a user's entitlement is reduced and the system has not yet had time to reclaim the resources to bring the user back in to compliance with their entitlement.

type EntitlementConsumption {
  # Consumer of entitlement. If not present, entitlement is consumed
  # at the user level
  consumer: EntitlementConsumer

  # Name of the entitlement
  name: String!

  # Value of the entitlement. Type Float to allow for values
  # values larger than possible with Int. Value is a
  # positive integer. Maximum value when retrieving entitlements
  # is 2^53 - 1
  value: Float!

  # Consumed amount of the entitlement. Type Float to allow for values
  # values larger than possible with Int. Value is a
  # positive integer. Maximum value when retrieving entitlements
  # is 2^53 - 1
  consumed: Float!

  # Available amount of the entitlement. Type Float to allow for values
  # values larger than possible with Int. Value is a
  # positive integer. Maximum value when retrieving entitlements
  # is 2^53 - 1
  available: Float!

  # Time this entitlement was first consumed
  firstConsumedAtEpochMs: Float

  # Time of most recent consumption of this entitlement
  lastConsumedAtEpochMs: Float
}

# An aggregated list of entitlement consumption information for an external user.
type ExternalEntitlementsConsumption  {
  # User's active entitlements
  entitlements: ExternalUserEntitlements!
  # User's entitlement consumption
  consumption: [EntitlementConsumption!]!
}

# Input type for getEntitlementsForUser query
input GetEntitlementsForUserInput {
  externalId: String!
}

type Query {
  # Retrieve effective entitlements for a given external user.
  getEntitlementsForUser(
    input: GetEntitlementsForUserInput!
  ): ExternalEntitlementsConsumption!
}

The getEntitlementsForUser query returns an aggregation of the specified user’s entitlement consumption information.

Possible Errors

  • NoEntitlementsError is returned if no entitlements have been defined for the user

  • ServiceError will be returned for internal errors.

Retrieving a user's entitlements and consumption using SDK.

do {
    let userEntitlementsConsumption = try await client.getEntitlementsForUserWithExternalId(
        externalId: externalId,
    ) 
} catch let error {
    // Handle error. An error may be thrown if the backend is unable perform
    // the operation due to invalid input, availability or security issues.
}

To remove all record of a user from the entitlements system call the removeEntitledUser mutation.

# Input for the removeEntitledUser mutation
input RemoveEntitledUserInput {
  externalId: String!
}

Last updated