Select programming language for code examples

linkThe policy object

Below you will find the various attributes for the policy resource, as well as the policy resource's relationships. Your policies define the different types of licenses that a given product offers. For example, you may offer yearly licenses, as well as shorter time-limited free trial licenses that lack certain entitlements.

Another example would be configuring a yearly software license that once expired, still functions normally, but is disallowed release upgrades after expiration. This is something you can accomplish using policies.

linkAttributes

  • linkdata.attributes.name

    string

    The name of the policy.

  • linkdata.attributes.duration

    integer

    The duration for the policy in seconds. When a new license implements the policy, the license's expiry is calculated with this value (i.e. time.now + policy.duration). If null, licenses will never expire.

  • linkdata.attributes.strict

    booleandefault=false

    When enabled, a license that implements the policy will be considered invalid if its machine limit, machine core limit, or processes limit is surpassed. In addition, strict requires a license to have at least 1 machine associated with it in order to pass validation.

  • linkdata.attributes.floating

    booleandefault=false

    When enabled, a license that implements the policy will be valid across multiple machines. Though this is not enforced i.e. it does not invalidate a license if it's associated with more than 1 machine unless the policy is strict.

  • linkdata.attributes.scheme

    string

    The cryptographic encryption/signature scheme used on license keys. Can be used to implement offline licensing by storing tamper-proof data within a license's key. When null or omitted, the license's key will be stored unchanged.

    Even though we're signing or encrypting license keys, that doesn't mean the value you specify is hidden. Keep in mind that the contents of the keys are usually base64url encoded (using RFC 4648, a URL-safe version of base64 which is supported in most programming languages), meaning they are publicly readable if decoded. For more info, see the signature section. Do not store sensitive information within keys, as the contents can be read by decoding the key.
    Options
    • ED25519_SIGN: Sign license keys with your account's Ed25519 signing key, using elliptic curve cryptography and SHA512. The given license key data will be base64url encoded and then prefixed with key/ before signing, and the signing data's signature will be base64url encoded and then appended onto the end of the signing data, delimited by the . character, e.g. key/{URLBASE64URL_KEY}.{URLBASE64URL_SIGNATURE}. This is our recommended signing scheme, but it may not be supported in your preferred programming language.
    • RSA_2048_PKCS1_PSS_SIGN_V2: Sign license keys with your account's 2048-bit RSA private key using RSA PKCS1-PSS padding, with a SHA256 digest, max salt length, and a SHA256 MGF1. The provided embedded dataset will be base64url encoded and then prefixed with key/ before signing, and the signing data's signature will be base64url encoded and then appended onto the end of the signing data, delimited by the . character, e.g. key/{URLBASE64URL_KEY}.{URLBASE64URL_SIGNATURE}, resulting in the final key. This is our recommended RSA scheme, but it may not be supported in your preferred programming language.
    • RSA_2048_PKCS1_SIGN_V2: Sign license keys with your account's 2048-bit RSA private key using RSA PKCS1 v1.5 padding, with a SHA256 digest. The provided embedded dataset will be base64url encoded and then prefixed with key/ before signing, and the signing data's signature will be base64url encoded and then appended onto the end of the signing data, delimited by the . character, e.g. key/{URLBASE64URL_KEY}.{URLBASE64URL_SIGNATURE}, resulting in the final key.
    • RSA_2048_PKCS1_ENCRYPT: Encrypt license keys with your account's 2048-bit RSA private key using RSA PKCS1 v1.5 padding. The provided dataset will be encrypted using your account's private key and then base64url encoded, resulting in the final key. The key can be decrypted using your account's public key. The key must contain no more than 245 bytes (please note this is byte length not string length).
    • RSA_2048_JWT_RS256: Encode a license claims payload into a JWT using the RS256 algorithm. The license key must be a valid JWT claims payload (i.e. a JSON encoded string). The JWT will be signed using your account's 2048-bit RSA private key and can be verified using your account's public key. The resulting key will be a full JSON Web Token. We do not modify your claims payload.
    • RSA_2048_PKCS1_PSS_SIGN: Deprecated: use v2. Sign license keys with your account's 2048-bit RSA private key using RSA PKCS1-PSS padding, with a SHA256 digest, max salt length, and a SHA256 MGF1. The provided embedded dataset will be base64url encoded, and its signature will be base64url encoded and then appended onto the end of the encoded key, delimited by the . character, e.g. {URLBASE64URL_KEY}.{URLBASE64URL_SIGNATURE}, resulting in the final key.
    • RSA_2048_PKCS1_SIGN: Deprecated: use v2. Sign license keys with your account's 2048-bit RSA private key using RSA PKCS1 v1.5 padding, with a SHA256 digest. The provided embedded dataset will be base64url encoded, and its signature will be base64url encoded and then appended onto the end of the encoded key, delimited by the . character, e.g. {URLBASE64URL_KEY}.{URLBASE64URL_SIGNATURE}, resulting in the final key.
  • linkdata.attributes.requireProductScope

    booleandefault=false

    When enabled, validating a license that implements the policy will require a product scope that matches the licenses's product relationship by its identifier (UUID).

  • linkdata.attributes.requirePolicyScope

    booleandefault=false

    When enabled, validating a license that implements the policy will require a policy scope that matches the licenses's policy relationship by its identifier (UUID).

  • linkdata.attributes.requireMachineScope

    booleandefault=false

    When enabled, validating a license that implements the policy will require a machine scope that matches at least 1 of the licenses's machine relationships by its identifier (UUID).

  • linkdata.attributes.requireFingerprintScope

    booleandefault=false

    When enabled, validating a license that implements the policy will require a fingerprint scope that matches at least 1 of the licenses's machine relationships by its fingerprint.

  • linkdata.attributes.requireComponentsScope

    booleandefault=false

    When enabled, validating a license that implements the policy will require a components scope that matches at least 1 of the licenses's machine components by its fingerprint.

  • linkdata.attributes.requireUserScope

    booleandefault=false

    When enabled, validating a license that implements the policy will require a user scope that matches the license's user relationship.

  • linkdata.attributes.requireChecksumScope

    booleandefault=false

    When enabled, validating a license that implements the policy will require a checksum scope to be provided, matching an accessible artifact for the license.

  • linkdata.attributes.requireVersionScope

    booleandefault=false

    When enabled, validating a license that implements the policy will require a version scope to be provided, matching an accessible release for the license.

  • linkdata.attributes.requireCheckIn

    booleandefault=false

    When enabled, a license that implements the policy will require check-in at a predefined interval to continue to pass validation i.e. if a license misses a check-in, it will be invalidated.

  • linkdata.attributes.checkInInterval

    string

    One of day, week, month or year. The frequency at which a license should check-in.

    Options
    • day: Require a license implementing the policy to check-in at least once every day to remain valid.
    • week: Require a license implementing the policy to check-in at least once every week to remain valid.
    • month: Require a license implementing the policy to check-in at least once every month to remain valid.
    • year: Require a license implementing the policy to check-in at least once every year to remain valid.
  • linkdata.attributes.checkInIntervalCount

    integer

    The number of intervals (specified in the check-in interval property) between each required check-in. For example, checkInInterval=week and checkInIntervalCount=2 requires check-in every 2 weeks. Must be a number between 1 and 365 inclusive.

  • linkdata.attributes.usePool

    booleandefault=false

    Whether or not to pull license keys from a finite pool of pre-determined keys. This is useful for invite-only programs such as a private beta, when you need a limited set of licenses, or when you want to define the keys manually. This cannot be changed later on.

  • linkdata.attributes.maxMachines

    integer

    The maximum number of machines a license implementing the policy can have associated with it. This is only enforced when the policy is strict. When null, an unlimited number of machines may be associated with a license if the policy is floating. Must be a number greater than 0, and must be equal to 1 for non-floating policies.

  • linkdata.attributes.maxProcesses

    integer

    The maximum number of machine processes a license implementing the policy can have associated with it, also depending on the policy's leasing strategy. When null, an unlimited number of machine processes may be associated with a license. Must be a number greater than 0.

  • linkdata.attributes.maxCores

    integer

    The maximum number of machine CPU cores a license implementing the policy can have associated with it. The count is the sum of all cores for the license's machines. This is inherited from the policy. When null, a license which implements the policy can have an unlimited number of CPU cores.

  • linkdata.attributes.maxUses

    integer

    The maximum number of uses a license implementing the policy can have. Cannot exceed 2,147,483,647, which is the maximum value of a 4 byte integer. When null, a license which implements the policy can have an unlimited number of uses. This attribute is not taken into account during license validation. See the license's usage-related actions for more details.

  • linkdata.attributes.protected

    booleandefault=inherited

    Whether or not the policy is protected. A protected policy disallows users the ability to create and manage licenses themselves, useful in situations where Keygen is only managed server-side or when you aren't listening for the appropriate user-initiated webhook events. If the account is protected, all policies automatically inherit that value when left blank.

  • linkdata.attributes.requireHeartbeat

    booleandefault=false

    Whether or not the policy requires its machines to maintain a heartbeat. When enabled, machines that do not have a heartbeat will fail validation with a HEARTBEAT_NOT_STARTED validation code. In addition, when enabled, new machines will automatically have their first heartbeat set upon creation. When disabled, heartbeats are optional.

    Please note: this only applies to machines, not processes. Processes always require a heartbeat.
  • linkdata.attributes.heartbeatDuration

    integer

    The heartbeat duration for the policy, in seconds. When a machine has an active heartbeat monitor, the machine must send heartbeat pings within this timeframe to remain activated. Must be greater than or equal to 1 minute (60).

  • linkdata.attributes.heartbeatCullStrategy

    stringdefault=DEACTIVATE_DEAD

    The strategy used for culling dead machines and processes.

    Please note: dead machines will not pass license validation. The resulting failed validation code will be HEARTBEAT_DEAD.
    Options
    • DEACTIVATE_DEAD: Automatically deactivate machines that fail to maintain their heartbeat pings. This is the default.
    • KEEP_DEAD: Mark machines that fail to maintain their heartbeat pings as dead, but do not deactivate.
  • linkdata.attributes.heartbeatResurrectionStrategy

    stringdefault=NO_REVIVE

    The strategy used for controlling whether or not dead machines and processes can be resurrected shortly after death. A resurrection occurs when a heartbeat ping is sent to a dead machine or process that is within its resurrection window.

    Please note: dead machines will not pass license validation. The resulting failed validation code will be HEARTBEAT_DEAD.
    Options
    • NO_REVIVE: Do not allow dead machines and processes to be revived. This is the default.
    • 1_MINUTE_REVIVE: A machine or process can be revived if it sends a ping within 1 minute from its time of death.
    • 2_MINUTE_REVIVE: A machine or process can be revived if it sends a ping within 2 minutes from its time of death.
    • 5_MINUTE_REVIVE: A machine or process can be revived if it sends a ping within 5 minutes from its time of death.
    • 10_MINUTE_REVIVE: A machine or process can be revived if it sends a ping within 10 minutes from its time of death.
    • 15_MINUTE_REVIVE: A machine or process can be revived if it sends a ping within 15 minutes from its time of death.
    • ALWAYS_REVIVE: A machine or process can always be revived. Requires a cull strategy of KEEP_DEAD.
  • linkdata.attributes.heartbeatBasis

    stringdefault=varies

    Control when a machine's initial heartbeat is started. By default, a machine's heartbeat is started on creation when its policy requires a heartbeat. Overwise, it is started on first ping.

    Please note: this only applies to machines, not processes. Processes always have a heartbeat basis of FROM_CREATION, because their heartbeat is required.
    Options
    • FROM_CREATION: Machine heartbeat is started immediately upon creation.
    • FROM_FIRST_PING: Mahine heartbeat is started after their first heartbeat ping event.
  • linkdata.attributes.machineUniquenessStrategy

    stringdefault=UNIQUE_PER_LICENSE

    The uniqueness validation strategy for machine fingerprints. You can utilize this to prevent duplicate fingerprints across a variety of scopes.

    This can be especially useful for disallowing trial licenses for a specific machine (i.e. device) that had previously completed a trial evaluation using another trial license. You would set the trial policy to UNIQUE_PER_POLICY, and then set any non-trial policies to UNIQUE_PER_LICENSE. This would effectively block a machine from using multiple trial licenses, while still allowing the machine to be associated with non-trial licenses.
    Options
    • UNIQUE_PER_ACCOUNT: Machine fingerprints must be unique across the entire Keygen account. This will block all duplicate fingerprints, regardless of whether or not the fingerprint belongs to another product, policy or license.
    • UNIQUE_PER_PRODUCT: Machine fingerprints must be unique across all licenses belonging to a product. This will block all duplicate fingerprints of the same product, regardless of whether or not the fingerprint belongs to another policy or license.
    • UNIQUE_PER_POLICY: Machine fingerprints must be unique across all licenses for the policy. This will block all duplicate fingerprints of the same policy, regardless of whether or not the fingerprint belongs to another license.
    • UNIQUE_PER_LICENSE: Machine fingerprints must be unique to the license. This will block all duplicate fingerprints for same license, but the same fingerprint can exist across different licenses. This is the default.
  • linkdata.attributes.machineMatchingStrategy

    stringdefault=MATCH_ANY

    The matching strategy for machine fingerprints supplied during a license validation.

    Options
    • MATCH_ANY: At least 1 of the supplied fingerprints must match a fingerprint for the license's associated machines. E.g. if 3 fingerprints are supplied, at least 1 of them must match.
    • MATCH_TWO: At least 2 of the supplied fingerprints must match a fingerprint for the license's associated machines. E.g. if 4 fingerprints are supplied, at least 2 of them must match.
    • MATCH_MOST: The majority of supplied fingerprints must match the fingerprints for the license's associated machines. E.g. if 3 fingerprints are supplied, at least 2 of them must match.
    • MATCH_ALL: All supplied fingerprints must match the fingerprints for the license's associated machines. E.g. if 3 fingerprints are supplied, all 3 of them must match.
  • linkdata.attributes.componentUniquenessStrategy

    stringdefault=UNIQUE_PER_MACHINE

    The uniqueness validation strategy for component fingerprints. You can utilize this to prevent duplicate fingerprints across a variety of scopes.

    This is especially useful for disallowing trial licenses for specific hardware that had previously completed a trial evaluation using another trial machine or license. You would set the trial policy to UNIQUE_PER_POLICY, and then set any non-trial policies to UNIQUE_PER_LICENSE. This would effectively block a device from using multiple trials even if e.g. the operating system was reinstalled.
    Options
    • UNIQUE_PER_ACCOUNT: Component fingerprints must be unique across the entire Keygen account. This will block all duplicate fingerprints, regardless of whether or not the fingerprint belongs to another product, policy or license.
    • UNIQUE_PER_PRODUCT: Component fingerprints must be unique across all licenses belonging to a product. This will block all duplicate fingerprints of the same product, regardless of whether or not the fingerprint belongs to another policy or license.
    • UNIQUE_PER_POLICY: Component fingerprints must be unique across all licenses for the policy. This will block all duplicate fingerprints of the same policy, regardless of whether or not the fingerprint belongs to another license.
    • UNIQUE_PER_LICENSE: Component fingerprints must also be unique to the license. This will block all duplicate fingerprints for same license, but the same fingerprint can exist across different licenses.
    • UNIQUE_PER_MACHINE: Component fingerprints must be unique to the machine. This will allow the same component to exist across multiple machines for the same license. This is the default.
  • linkdata.attributes.componentMatchingStrategy

    stringdefault=MATCH_ANY

    The matching strategy for component fingerprints supplied during a license validation.

    This is especially useful for managing individual hardware components of a given device, e.g. HDD ID, mobo ID, MAC addresses, IP addresses, etc., and then requiring that some, most, or all components match during a license validation. These can be managed through the components resource.
    Options
    • MATCH_ANY: At least 1 of the supplied fingerprints must match a fingerprint for the machine's associated components. E.g. if 3 fingerprints are supplied, at least 1 of them must match.
    • MATCH_TWO: At least 2 of the supplied fingerprints must match a fingerprint for the machine's associated components. E.g. if 4 fingerprints are supplied, at least 2 of them must match.
    • MATCH_MOST: The majority of supplied fingerprints must match the fingerprints for the machine's associated components. E.g. if 3 fingerprints are supplied, at least 2 of them must match.
    • MATCH_ALL: All supplied fingerprints must match the fingerprints for the machine's associated components. E.g. if 3 fingerprints are supplied, all 3 of them must match.
  • linkdata.attributes.expirationStrategy

    stringdefault=RESTRICT_ACCESS

    The strategy for expired licenses during a license validation and when accessing releases.

    This is useful in scenarios where you want to allow normal product usage for expired licenses and access to older releases published prior their expiry, but restrict access to newer releases published after the expiry, or when a license has a maintainence window after which upgrades are paused until renewal. Expiration strategies may change license validation and authentication behavior (read more).
    Options
    • RESTRICT_ACCESS: Expired licenses can continue to access releases published prior to their expiry, but automatic upgrades are disabled. Validation scopes take precedence over expiry check during license validation.
    • REVOKE_ACCESS: Expired licenses are no longer able to access any releases, including past releases and upgrades. Expiry check takes precedence over scopes during license validation.
    • MAINTAIN_ACCESS: Expired licenses can continue to access releases published prior to their expiry, but automatic upgrades are disabled. Validation scopes take precedence over expiry check during license validation. In addition, validations with an EXPIRED code will return valid=true.
    • ALLOW_ACCESS: Expired licenses can access any releases, including past releases and future automatic upgrades. Validation scopes take precedence over expiry check during license validation. In addition, validations with an EXPIRED code will return valid=true.
  • linkdata.attributes.expirationBasis

    stringdefault=FROM_CREATION

    Control when a license's initial expiry is set. For example, you may want to initialize a license's expiry after its first activation, rather than at time of creation. By default, a license's expiration date is set on creation. Any interim expiry value will be null.

    When using an expiration basis other than FROM_CREATION, the license's expiration is set asychronously, after the event has been processed in our systems. For example, when using a FROM_FIRST_VALIDATION expiration basis, the license's expiry will not immediately be set during its first validation request and then subsequently included in the validation response. Rather, it will be set after the request and response lifecycle, once the event has fully propagated through our systems. This could take up to a few minutes.
    This is especially useful in scenarios where you're generating licenses upfront in bulk for later distribution, e.g. as part of a digital component to a physical product. Instead of distributing licenses that have expirations already set, and potentially expired given enough time, you can instead set the expiry on some event in the future, e.g. validation or activation.
    Options
    • FROM_CREATION: License expirations are set immediately upon creation.
    • FROM_FIRST_VALIDATION: License expirations are set after their first license validation event.
    • FROM_FIRST_ACTIVATION: License expirations are set after their first machine activation event.
    • FROM_FIRST_DOWNLOAD: License expirations are set after their first release download event.
    • FROM_FIRST_USE: License expirations are set after their first usage increment event.
      Note: "usage" is not activation or validation.FROM_FIRST_USE is for a license's usage.
  • linkdata.attributes.renewalBasis

    stringdefault=FROM_EXPIRY

    Control how a license's expiry is extended during renewal. For example, you may want to extend the license's expiry from the current time, instead of from the license's current expiry value.

    Options
    • FROM_EXPIRY: License expiry is extended from the license's current expiry value, i.e. license.expiry = license.expiry + policy.duration. This is the default.
    • FROM_NOW: License expiry is extended from the current time, i.e. license.expiry = time.now + policy.duration.
  • linkdata.attributes.transferStrategy

    stringdefault=KEEP_EXPIRY

    Control whether a license's expiration is reset when transferred to this policy.

    This is especially useful when transferring a license from a policy with a short duration to one with a longer duration. For example, upgrading from a 14 day free trial license to a yearly license.
    Options
    • RESET_EXPIRY: Reset the transferred license's expiry from the time of transfer. For example, if the license had an expiry 3 months from now, and the new policy has a duration of 1 year, transferring would reset the expiry to 1 year from the time of transfer. When the policy has no duration, the license's expiry is removed.
    • KEEP_EXPIRY: Do not change the license's current expiry. This is the default.
  • linkdata.attributes.authenticationStrategy

    stringdefault=TOKEN

    The strategy used for authenticating as a license, for client-side integrations.

    This defines the ways a license is allowed to authenticate with the API. To disable license authentication, e.g. in an entirely server-side integration, set this to NONE.
    Options
    • TOKEN: Allow licenses to authenticate using a license token. This is the default.
    • LICENSE: Allow licenses to authenticate using a license key.
    • MIXED: Allow both license token and license key authentication (each covered above).
    • NONE: Disable the ability for licenses to authenticate with the API.
  • linkdata.attributes.leasingStrategy

    stringdefault=PER_MACHINE

    The strategy used for leasing machine processes.

    This defines how processes are leased and counted. For example, a PER_MACHINE leasing strategy would count processes per-machine, meaning if a policy allowed up to 5 processes, it would allow a license with 2 machines, 5 processes each; similarly, with a PER_LICENSE leasing strategy, processes are counted collectively across all of a license's machines, meaning a license will not be able to create 10 processes across 2 machines, because the sum of processes would be over their limit of 5 processes per-license.
    Options
    • PER_MACHINE: Machine processes are counted per-machine, i.e. limits are enforced individually for each machine. This is the default.
    • PER_LICENSE: Machine processes are counted per-license, i.e. collectively across all of a license's machines.
  • linkdata.attributes.overageStrategy

    stringdefault=NO_OVERAGE

    The strategy used for allowing machine, core and process overages. Set to NO_OVERAGE to disable overages altogether (attempts to exceed a limit will then result in an error).

    This defines an overage allowance for a license. This allowance effects a license's machine limit, machine core limit, and its machine process limit. Giving a license an overage allowance may be beneficial in environments where rolling restarts of the application are common, or another situation where overages are expected. This lets you allow overages, bounded and unbounded, while handling the unique validation codes to ensure total license compliance.
    Options
    • ALWAYS_ALLOW_OVERAGE: The license may exceed its limits, and doing so will not effect the licenses validity, i.e. the following validation codes will return valid=true: TOO_MANY_MACHINES, TOO_MANY_CORES, TOO_MANY_PROCESSES.
    • ALLOW_1_25X_OVERAGE: The license may exceed its limits, up to a maximum of 1.25x. Exceeding a limit will not effect the license's validity right away, i.e. the following validation codes will return valid=true: TOO_MANY_MACHINES, TOO_MANY_CORES, TOO_MANY_PROCESSES. The license will begin to fail validation once the 1.25x allowance has been exceeded. When using a 1.25x allowance, all resource limits must be divisible by 4.
    • ALLOW_1_5X_OVERAGE: The license may exceed its limits, up to a maximum of 1.5x. Exceeding a limit will not effect the license's validity right away, i.e. the following validation codes will return valid=true: TOO_MANY_MACHINES, TOO_MANY_CORES, TOO_MANY_PROCESSES. The license will begin to fail validation once the 1.5x allowance has been exceeded. When using a 1.5x allowance, all resource limits must be divisible by 2.
    • ALLOW_2X_OVERAGE: The license may exceed its limits, up to a maximum of 2x. Exceeding a limit will not effect the license's validity right away, i.e. the following validation codes will return valid=true: TOO_MANY_MACHINES, TOO_MANY_CORES, TOO_MANY_PROCESSES. The license will begin to fail validation once the 2x allowance has been exceeded.
    • NO_OVERAGE: Do not allow overages. Attempts to exceed limits will fail. This is the default.
  • linkdata.attributes.metadata

    object<string, any>

    Object containing policy metadata.

  • linkdata.attributes.created

    timestamp (iso8601)read only

    When the policy was created.

  • linkdata.attributes.updated

    timestamp (iso8601)read only

    When the policy was last updated.

linkRelationships

  • linkdata.relationships.account

    individual

    The account that the policy belongs to.

  • linkdata.relationships.environment

    individualent onlyThese relationships are only available for accounts on an Ent tier.

    The environment that the policy belongs to.

  • linkdata.relationships.product

    individual

    The product that the policy is associated with.

  • linkdata.relationships.pool

    collection

    The pool of pre-determined keys for the policy.

  • linkdata.relationships.licenses

    collection

    The licenses that implement the policy.

Example object

{
"data": {
"id": "0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
"type": "policies",
"links": {
"self": "/v1/accounts/{ACCOUNT}/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065"
},
"attributes": {
"name": "Premium Add-On",
"duration": 1209600,
"strict": false,
"floating": true,
"scheme": null,
"requireProductScope": false,
"requirePolicyScope": false,
"requireMachineScope": false,
"requireFingerprintScope": false,
"requireComponentsScope": false,
"requireUserScope": false,
"requireChecksumScope": false,
"requireVersionScope": false,
"requireCheckIn": false,
"checkInInterval": null,
"checkInIntervalCount": null,
"usePool": false,
"maxMachines": 5,
"maxProcesses": null,
"maxCores": null,
"maxUses": null,
"encrypted": false,
"protected": false,
"requireHeartbeat": false,
"heartbeatDuration": null,
"heartbeatCullStrategy": "DEACTIVATE_DEAD",
"heartbeatResurrectionStrategy": "NO_REVIVE",
"heartbeatBasis": "FROM_FIRST_PING",
"machineUniquenessStrategy": "UNIQUE_PER_LICENSE",
"machineMatchingStrategy": "MATCH_ALL",
"componentUniquenessStrategy": "UNIQUE_PER_MACHINE",
"componentMatchingStrategy": "MATCH_ALL",
"expirationStrategy": "RESTRICT_ACCESS",
"expirationBasis": "FROM_CREATION",
"renewalBasis": "FROM_EXPIRY",
"transferStrategy": "KEEP_EXPIRY",
"authenticationStrategy": "TOKEN",
"leasingStrategy": "PER_MACHINE",
"overageStrategy": "NO_OVERAGE",
"metadata": {},
"created": "2017-01-02T20:26:53.464Z",
"updated": "2017-01-02T20:26:53.464Z"
},
"relationships": {
"account": {
"links": {
"related": "/v1/accounts/{ACCOUNT}"
},
"data": {
"type": "accounts",
"id": "{ACCOUNT}"
}
},
"product": {
"links": {
"related": "/v1/accounts/{ACCOUNT}/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/product"
},
"data": {
"type": "products",
"id": "3ab38aae-bbf7-4846-9c32-af9d94bf5ad4"
}
},
"pool": {
"links": {
"related": "/v1/accounts/{ACCOUNT}/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/pool"
}
},
"licenses": {
"links": {
"related": "/v1/accounts/{ACCOUNT}/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/licenses"
}
},
"entitlements": {
"links": {
"related": "/v1/accounts/{ACCOUNT}/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements"
}
}
}
}
}

linkCreate a policy

Creates a new policy resource.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: either an admin, an environment, or the product it belongs to.

linkURL Parameters

  • link<account>

    stringrequired

    The identifier (UUID) or slug of your Keygen account.

linkAttributes

  • linkdata.attributes.name

    stringrequired

    The name of the policy.

  • linkdata.attributes.duration

    integeroptional

    The duration for the policy in seconds. When a new license implements the policy, the license's expiry is calculated with this value (i.e. time.now + policy.duration). If null, licenses will never expire.

  • linkdata.attributes.scheme

    stringoptional

    The cryptographic encryption/signature scheme used on license keys. Can be used to implement offline licensing by storing tamper-proof data within a license's key. When null or omitted, the license's key will be stored unchanged.

    Even though we're signing or encrypting license keys, that doesn't mean the value you specify is hidden. Keep in mind that the contents of the keys are usually base64url encoded (using RFC 4648, a URL-safe version of base64 which is supported in most programming languages), meaning they are publicly readable if decoded. For more info, see the signature section. Do not store sensitive information within keys, as the contents can be read by decoding the key.
    Options
    • ED25519_SIGN: Sign license keys with your account's Ed25519 signing key, using elliptic curve cryptography and SHA512. The given license key data will be base64url encoded and then prefixed with key/ before signing, and the signing data's signature will be base64url encoded and then appended onto the end of the signing data, delimited by the . character, e.g. key/{URLBASE64URL_KEY}.{URLBASE64URL_SIGNATURE}. This is our recommended signing scheme, but it may not be supported in your preferred programming language. Signatures are deterministic.
    • RSA_2048_PKCS1_PSS_SIGN_V2: Sign license keys with your account's 2048-bit RSA private key using RSA PKCS1-PSS padding, with a SHA256 digest, max salt length, and a SHA256 MGF1. The provided embedded dataset will be base64url encoded and then prefixed with key/ before signing, and the signing data's signature will be base64url encoded and then appended onto the end of the signing data, delimited by the . character, e.g. key/{URLBASE64URL_KEY}.{URLBASE64URL_SIGNATURE}, resulting in the final key. This is our recommended RSA scheme, but it may not be supported in your preferred programming language. Signatures are non-deterministic.
    • RSA_2048_PKCS1_SIGN_V2: Sign license keys with your account's 2048-bit RSA private key using RSA PKCS1 v1.5 padding, with a SHA256 digest. The provided embedded dataset will be base64url encoded and then prefixed with key/ before signing, and the signing data's signature will be base64url encoded and then appended onto the end of the signing data, delimited by the . character, e.g. key/{URLBASE64URL_KEY}.{URLBASE64URL_SIGNATURE}, resulting in the final key. Signatures are deterministic.
    • RSA_2048_PKCS1_ENCRYPT: Encrypt license keys with your account's 2048-bit RSA private key using RSA PKCS1 v1.5 padding. The provided dataset will be encrypted using your account's private key and then base64url encoded, resulting in the final key. The key can be decrypted using your account's public key. The key must contain no more than 245 bytes (please note this is byte length not string length).
    • RSA_2048_JWT_RS256: Encode a license claims payload into a JWT using the RS256 algorithm. The license key must be a valid JWT claims payload (i.e. a JSON encoded string). The JWT will be signed using your account's 2048-bit RSA private key and can be verified using your account's public key. The resulting key will be a full JSON Web Token. We do not modify your claims payload.
    • RSA_2048_PKCS1_PSS_SIGN: Deprecated: use v2. Sign license keys with your account's 2048-bit RSA private key using RSA PKCS1-PSS padding, with a SHA256 digest, max salt length, and a SHA256 MGF1. The provided embedded dataset will be base64url encoded, and its signature will be base64url encoded and then appended onto the end of the encoded key, delimited by the . character, e.g. {URLBASE64URL_KEY}.{URLBASE64URL_SIGNATURE}, resulting in the final key.
    • RSA_2048_PKCS1_SIGN: Deprecated: use v2. Sign license keys with your account's 2048-bit RSA private key using RSA PKCS1 v1.5 padding, with a SHA256 digest. The provided embedded dataset will be base64url encoded, and its signature will be base64url encoded and then appended onto the end of the encoded key, delimited by the . character, e.g. {URLBASE64URL_KEY}.{URLBASE64URL_SIGNATURE}, resulting in the final key.
  • linkdata.attributes.strict

    booleanoptional

    When enabled, a license that implements the policy will be considered invalid if its machine limit, machine core limit, or processes limit is surpassed. In addition, strict requires a license to have at least 1 machine associated with it in order to pass validation.

  • linkdata.attributes.floating

    booleanoptional

    When enabled, a license that implements the policy will be valid across multiple machines. Though this is not enforced i.e. it does not invalidate a license if it's associated with more than 1 machine unless the policy is strict.

  • linkdata.attributes.requireProductScope

    booleanoptional

    When enabled, validating a license that implements the policy will require a product scope that matches the licenses's product relationship by its identifier (UUID).

  • linkdata.attributes.requirePolicyScope

    booleanoptional

    When enabled, validating a license that implements the policy will require a policy scope that matches the licenses's policy relationship by its identifier (UUID).

  • linkdata.attributes.requireMachineScope

    booleanoptional

    When enabled, validating a license that implements the policy will require a machine scope that matches at least 1 of the licenses's machine relationships by its identifier (UUID).

  • linkdata.attributes.requireFingerprintScope

    booleanoptional

    When enabled, validating a license that implements the policy will require a fingerprint scope that matches at least 1 of the licenses's machine relationships by its fingerprint.

  • linkdata.attributes.requireComponentsScope

    booleanoptional

    When enabled, validating a license that implements the policy will require a components scope that matches at least 1 of the licenses's machine components by its fingerprint.

  • linkdata.attributes.requireUserScope

    booleanoptional

    When enabled, validating a license that implements the policy will require a user scope that matches the license's user relationship.

  • linkdata.attributes.requireChecksumScope

    booleanoptional

    When enabled, validating a license that implements the policy will require a checksum scope to be provided, matching an accessible artifact for the license.

  • linkdata.attributes.requireVersionScope

    booleanoptional

    When enabled, validating a license that implements the policy will require a version scope to be provided, matching an accessible release for the license.

  • linkdata.attributes.requireCheckIn

    booleanoptional

    When enabled, a license that implements the policy will require check-in at a predefined interval to continue to pass validation i.e. if a license misses a check-in, it will be invalidated.

  • linkdata.attributes.checkInInterval

    stringoptional

    One of day, week, month or year. The frequency at which a license should check-in.

    Options
    • day: Require a license implementing the policy to check-in at least once every day to remain valid.
    • week: Require a license implementing the policy to check-in at least once every week to remain valid.
    • month: Require a license implementing the policy to check-in at least once every month to remain valid.
    • year: Require a license implementing the policy to check-in at least once every year to remain valid.
  • linkdata.attributes.checkInIntervalCount

    integeroptional

    The number of intervals (specified in the check-in interval property) between each required check-in. For example, checkInInterval=week and checkInIntervalCount=2 requires check-in every 2 weeks. Must be a number between 1 and 365 inclusive.

  • linkdata.attributes.usePool

    booleanoptional

    Whether or not to pull license keys from a finite pool of pre-determined keys. This is useful for invite-only programs such as a private beta, when you need a limited set of licenses, or when you want to define the keys manually. This cannot be changed later on.

  • linkdata.attributes.maxMachines

    integeroptional

    The maximum number of machines a license implementing the policy can have associated with it. This is only enforced when the policy is strict. When null, an unlimited number of machines may be associated with a license if the policy is floating. Must be a number greater than 0, and must be equal to 1 for non-floating policies.

  • linkdata.attributes.maxProcesses

    integeroptional

    The maximum number of machine processes a license implementing the policy can have associated with it, also depending on the policy's leasing strategy. When null, an unlimited number of machine processes may be associated with a license. Must be a number greater than 0.

  • linkdata.attributes.maxCores

    integeroptional

    The maximum number of machine CPU cores a license implementing the policy can have associated with it. The count is the sum of all cores for the license's machines. This is inherited from the policy. When null, a license which implements the policy can have an unlimited number of CPU cores.

  • linkdata.attributes.maxUses

    integeroptional

    The maximum number of uses a license implementing the policy can have. Cannot exceed 2,147,483,647, which is the maximum value of a 4 byte integer. When null, a license which implements the policy can have an unlimited number of uses. This attribute is not taken into account during license validation. See the license's usage-related actions for more details.

  • linkdata.attributes.protected

    booleanoptional

    Whether or not the policy is protected. A protected policy disallows users the ability to create and manage licenses themselves, useful in situations where Keygen is only managed server-side or when you aren't listening for the appropriate user-initiated webhook events. If the account is protected, all policies automatically inherit that value when left blank.

  • linkdata.attributes.requireHeartbeat

    booleanoptional

    Whether or not the policy requires its machines to maintain a heartbeat. When enabled, machines that do not have a heartbeat will fail validation with a HEARTBEAT_NOT_STARTED validation code. In addition, when enabled, new machines will automatically have their first heartbeat set upon creation. When disabled, heartbeats are optional.

    Please note: this only applies to machines, not processes. Processes always require a heartbeat.
  • linkdata.attributes.heartbeatDuration

    integeroptional

    The heartbeat duration for the policy, in seconds. When a machine has an active heartbeat monitor, the machine must send heartbeat pings within this timeframe to remain activated. Must be greater than or equal to 1 minute (60).

  • linkdata.attributes.heartbeatCullStrategy

    stringoptional

    The strategy used for culling dead machines and processes.

    Please note: dead machines will not pass license validation. The resulting failed validation code will be HEARTBEAT_DEAD.
    Options
    • DEACTIVATE_DEAD: Automatically deactivate machines that fail to maintain their heartbeat pings. This is the default.
    • KEEP_DEAD: Mark machines that fail to maintain their heartbeat pings as dead, but do not deactivate.
  • linkdata.attributes.heartbeatResurrectionStrategy

    stringoptional

    The strategy used for controlling whether or not dead machines and processes can be resurrected shortly after death. A resurrection occurs when a heartbeat ping is sent to a dead machine or process that is within its resurrection window.

    Please note: dead machines will not pass license validation. The resulting failed validation code will be HEARTBEAT_DEAD.
    Options
    • NO_REVIVE: Do not allow dead machines and processes to be revived. This is the default.
    • 1_MINUTE_REVIVE: A machine or process can be revived if it sends a ping within 1 minute from its time of death.
    • 2_MINUTE_REVIVE: A machine or process can be revived if it sends a ping within 2 minutes from its time of death.
    • 5_MINUTE_REVIVE: A machine or process can be revived if it sends a ping within 5 minutes from its time of death.
    • 10_MINUTE_REVIVE: A machine or process can be revived if it sends a ping within 10 minutes from its time of death.
    • 15_MINUTE_REVIVE: A machine or process can be revived if it sends a ping within 15 minutes from its time of death.
    • ALWAYS_REVIVE: A machine or process can always be revived. Requires a cull strategy of KEEP_DEAD.
  • linkdata.attributes.heartbeatBasis

    stringoptional

    Control when a machine's initial heartbeat is started. By default, a machine's heartbeat is started on creation when its policy requires a heartbeat. Overwise, it is started on first ping.

    Please note: this only applies to machines, not processes. Processes always have a heartbeat basis of FROM_CREATION, because their heartbeat is required.
    Options
    • FROM_CREATION: Machine heartbeat is started immediately upon creation.
    • FROM_FIRST_PING: Mahine heartbeat is started after their first heartbeat ping event.
  • linkdata.attributes.machineUniquenessStrategy

    stringoptional

    The uniqueness validation strategy for machine fingerprints. You can utilize this to prevent duplicate fingerprints across a variety of scopes.

    This can be especially useful for disallowing trial licenses for a specific machine (i.e. device) that had previously completed a trial evaluation using another trial license. You would set the trial policy to UNIQUE_PER_POLICY, and then set any non-trial policies to UNIQUE_PER_LICENSE. This would effectively block a machine from using multiple trial licenses, while still allowing the machine to be associated with non-trial licenses.
    Options
    • UNIQUE_PER_ACCOUNT: Machine fingerprints must be unique across the entire Keygen account. This will block all duplicate fingerprints, regardless of whether or not the fingerprint belongs to another product, policy or license.
    • UNIQUE_PER_PRODUCT: Machine fingerprints must be unique across all licenses belonging to a product. This will block all duplicate fingerprints of the same product, regardless of whether or not the fingerprint belongs to another policy or license.
    • UNIQUE_PER_POLICY: Machine fingerprints must be unique across all licenses for the policy. This will block all duplicate fingerprints of the same policy, regardless of whether or not the fingerprint belongs to another license.
    • UNIQUE_PER_LICENSE: Machine fingerprints must be unique to the license. This will block all duplicate fingerprints for same license, but the same fingerprint can exist across different licenses. This is the default.
  • linkdata.attributes.machineMatchingStrategy

    stringoptional

    The matching strategy for machine fingerprints supplied during a license validation.

    Options
    • MATCH_ANY: At least 1 of the supplied fingerprints must match a fingerprint for the license's associated machines. E.g. if 3 fingerprints are supplied, at least 1 of them must match.
    • MATCH_TWO: At least 2 of the supplied fingerprints must match a fingerprint for the license's associated machines. E.g. if 4 fingerprints are supplied, at least 2 of them must match.
    • MATCH_MOST: The majority of supplied fingerprints must match the fingerprints for the license's associated machines. E.g. if 3 fingerprints are supplied, at least 2 of them must match.
    • MATCH_ALL: All supplied fingerprints must match the fingerprints for the license's associated machines. E.g. if 3 fingerprints are supplied, all 3 of them must match.
  • linkdata.attributes.componentUniquenessStrategy

    stringoptional

    The uniqueness validation strategy for machine and component fingerprints. You can utilize this to prevent duplicate fingerprints across a variety of scopes. Uniqueness is per-type, i.e. machine and component fingerprints will never conflict. As a baseline, machine fingerprints will always be unique per-license, and component fingerprints will always be unique per-machine.

    This is especially useful for disallowing trial licenses for specific hardware that had previously completed a trial evaluation using another trial machine or license. You would set the trial policy to UNIQUE_PER_POLICY, and then set any non-trial policies to UNIQUE_PER_LICENSE. This would effectively block a device from using multiple trials even if e.g. the operating system was reinstalled.
    Options
    • UNIQUE_PER_ACCOUNT: Component fingerprints must be unique across the entire Keygen account. This will block all duplicate fingerprints, regardless of whether or not the fingerprint belongs to another product, policy or license.
    • UNIQUE_PER_PRODUCT: Component fingerprints must be unique across all licenses belonging to a product. This will block all duplicate fingerprints of the same product, regardless of whether or not the fingerprint belongs to another policy or license.
    • UNIQUE_PER_POLICY: Component fingerprints must be unique across all licenses for the policy. This will block all duplicate fingerprints of the same policy, regardless of whether or not the fingerprint belongs to another license.
    • UNIQUE_PER_LICENSE: Component fingerprints must also be unique to the license. This will block all duplicate fingerprints for same license, but the same fingerprint can exist across different licenses.
    • UNIQUE_PER_MACHINE: Component fingerprints must be unique to the machine. This will allow the same component to exist across multiple machines for the same license. This is the default.
  • linkdata.attributes.componentMatchingStrategy

    stringoptional

    The matching strategy for component fingerprints supplied during a license validation.

    This is especially useful for managing individual hardware components of a given device, e.g. HDD ID, mobo ID, MAC addresses, IP addresses, etc., and then requiring that some, most, or all components match during a license validation. These can be managed through the components resource.
    Options
    • MATCH_ANY: At least 1 of the supplied fingerprints must match a fingerprint for the machine's associated components. E.g. if 3 fingerprints are supplied, at least 1 of them must match.
    • MATCH_TWO: At least 2 of the supplied fingerprints must match a fingerprint for the machine's associated components. E.g. if 4 fingerprints are supplied, at least 2 of them must match.
    • MATCH_MOST: The majority of supplied fingerprints must match the fingerprints for the machine's associated components. E.g. if 3 fingerprints are supplied, at least 2 of them must match.
    • MATCH_ALL: All supplied fingerprints must match the fingerprints for the machine's associated components. E.g. if 3 fingerprints are supplied, all 3 of them must match.
  • linkdata.attributes.expirationStrategy

    stringoptional

    The strategy for expired licenses during a license validation and when accessing releases.

    This is useful in scenarios where you want to allow normal product usage for expired licenses and access to older releases published prior their expiry, but restrict access to newer releases published after the expiry, or when a license has a maintainence window after which upgrades are paused until renewal. Expiration strategies may change license validation and authentication behavior (read more).
    Options
    • RESTRICT_ACCESS: Expired licenses can continue to access releases published prior to their expiry, but automatic upgrades are disabled. Validation scopes take precedence over expiry check during license validation.
    • REVOKE_ACCESS: Expired licenses are no longer able to access any releases, including past releases and upgrades. Expiry check takes precedence over scopes during license validation.
    • MAINTAIN_ACCESS: Expired licenses can continue to access releases published prior to their expiry, but automatic upgrades are disabled. Validation scopes take precedence over expiry check during license validation. In addition, validations with an EXPIRED code will return valid=true.
    • ALLOW_ACCESS: Expired licenses can access any releases, including past releases and future automatic upgrades. Validation scopes take precedence over expiry check during license validation. In addition, validations with an EXPIRED code will return valid=true.
  • linkdata.attributes.expirationBasis

    stringoptional

    Control when a license's initial expiry is set. By default, a license's expiration date is set on creation.

    Options
    • FROM_CREATION: License expirations are set immediately upon creation.
    • FROM_FIRST_VALIDATION: License expirations are set after their first license validation event.
    • FROM_FIRST_ACTIVATION: License expirations are set after their first machine activation event.
    • FROM_FIRST_DOWNLOAD: License expirations are set after their first release download event.
    • FROM_FIRST_USE: License expirations are set after their first usage increment event.
      Note: "usage" is not activation or validation.FROM_FIRST_USE is for a license's usage.
  • linkdata.attributes.renewalBasis

    stringoptional

    Control how a license's expiry is extended during renewal. For example, you may want to extend the license's expiry from the current time, instead of from the license's current expiry value.

    Options
    • FROM_EXPIRY: License expiry is extended from the license's current expiry value, i.e. license.expiry = license.expiry + policy.duration. This is the default.
    • FROM_NOW: License expiry is extended from the current time, i.e. license.expiry = time.now + policy.duration.
  • linkdata.attributes.transferStrategy

    stringoptional

    Control whether a license's expiration is reset when transferred to this policy.

    This is especially useful when transferring a license from a policy with a short duration to one with a longer duration. For example, upgrading from a 14 day free trial license to a yearly license.
    Options
    • RESET_EXPIRY: Reset the transferred license's expiry from the time of transfer. For example, if the license had an expiry 3 months from now, and the new policy has a duration of 1 year, transferring would reset the expiry to 1 year from the time of transfer. When the policy has no duration, the license's expiry is removed.
    • KEEP_EXPIRY: Do not change the license's current expiry. This is the default.
  • linkdata.attributes.authenticationStrategy

    stringoptional

    The strategy used for authenticating as a license, for client-side integrations.

    Options
    • TOKEN: Allow licenses to authenticate using a license token. This is the default.
    • LICENSE: Allow licenses to authenticate using a license key.
    • MIXED: Allow both license token and license key authentication (each covered above).
    • NONE: Disable the ability for licenses to authenticate with the API.
  • linkdata.attributes.leasingStrategy

    stringoptional

    The strategy used for leasing machine processes.

    This defines how processes are leased and counted. For example, a PER_MACHINE leasing strategy would count processes per-machine, meaning if a policy allowed up to 5 processes, it would allow a license with 2 machines, 5 processes each; similarly, with a PER_LICENSE leasing strategy, processes are counted collectively across all of a license's machines, meaning a license will not be able to create 10 processes across 2 machines, because the sum of processes would be over their limit of 5 processes per-license.
    Options
    • PER_MACHINE: Machine processes are counted per-machine, i.e. limits are enforced individually for each machine. This is the default.
    • PER_LICENSE: Machine processes are counted per-license, i.e. collectively across all of a license's machines.
  • linkdata.attributes.overageStrategy

    stringoptional

    The strategy used for allowing machine, core and process overages. Set to NO_OVERAGE to disable overages altogether (attempts to exceed a limit will then result in an error).

    This defines an overage allowance for a license. This allowance effects a license's machine limit, machine core limit, and its machine process limit. Giving a license an overage allowance may be beneficial in environments where rolling restarts of the application are common, or another situation where overages are expected. This lets you allow overages, bounded and unbounded, while handling the unique validation codes to ensure total license compliance.
    Options
    • ALWAYS_ALLOW_OVERAGE: The license may exceed its limits, and doing so will not effect the licenses validity, i.e. the following validation codes will return valid=true: TOO_MANY_MACHINES, TOO_MANY_CORES, TOO_MANY_PROCESSES.
    • ALLOW_1_25X_OVERAGE: The license may exceed its limits, up to a maximum of 1.25x. Exceeding a limit will not effect the license's validity right away, i.e. the following validation codes will return valid=true: TOO_MANY_MACHINES, TOO_MANY_CORES, TOO_MANY_PROCESSES. The license will begin to fail validation once the 1.25x allowance has been exceeded. When using a 1.25x allowance, all resource limits must be divisible by 4.
    • ALLOW_1_5X_OVERAGE: The license may exceed its limits, up to a maximum of 1.5x. Exceeding a limit will not effect the license's validity right away, i.e. the following validation codes will return valid=true: TOO_MANY_MACHINES, TOO_MANY_CORES, TOO_MANY_PROCESSES. The license will begin to fail validation once the 1.5x allowance has been exceeded. When using a 1.5x allowance, all resource limits must be divisible by 2.
    • ALLOW_2X_OVERAGE: The license may exceed its limits, up to a maximum of 2x. Exceeding a limit will not effect the license's validity right away, i.e. the following validation codes will return valid=true: TOO_MANY_MACHINES, TOO_MANY_CORES, TOO_MANY_PROCESSES. The license will begin to fail validation once the 2x allowance has been exceeded.
    • NO_OVERAGE: Do not allow overages. Attempts to exceed limits will fail. This is the default.
  • linkdata.attributes.metadata

    object<string, any>optional

    Object containing policy metadata.

linkRelationships

linkReturns

A 201 Created response will be returned along with the new policy object.

Upon error, an errors object will be returned along with an HTTP status code indicating the type of error. When an error occurs, the data property will not be included.

Definition

https://api.keygen.sh/v1/accounts/{ACCOUNT}/policies

Example request

const fetch = require("node-fetch")
 
const response = await fetch("https://api.keygen.sh/v1/accounts/{ACCOUNT}/policies", {
method: "POST",
headers: {
"Content-Type": "application/vnd.api+json",
"Accept": "application/vnd.api+json",
"Authorization": "Bearer {TOKEN}"
},
body: JSON.stringify({
"data": {
"type": "policies",
"attributes": {
"name": "Basic"
},
"relationships": {
"product": {
"data": { "type": "product", "id": "3ab38aae-bbf7-4846-9c32-af9d94bf5ad4" }
}
}
}
})
})
 
const { data, errors } = await response.json()
import requests
import json
 
res = requests.post(
"https://api.keygen.sh/v1/accounts/{ACCOUNT}/policies",
headers={
"Content-Type": "application/vnd.api+json",
"Accept": "application/vnd.api+json",
"Authorization": "Bearer {TOKEN}"
},
data=json.dumps({
"data": {
"type": "policies",
"attributes": {
"name": "Basic"
},
"relationships": {
"product": {
"data": { "type": "product", "id": "3ab38aae-bbf7-4846-9c32-af9d94bf5ad4" }
}
}
}
})
).json()
import SwiftyJSON
import Alamofire
 
Alamofire.request("https://api.keygen.sh/v1/accounts/{ACCOUNT}/policies",
method: .post,
headers: [
"Content-Type": "application/vnd.api+json",
"Accept": "application/vnd.api+json",
"Authorization": "Bearer {TOKEN}"
],
parameters: [
"data": [
"type": "policies",
"attributes": [
"name": "Basic"
],
"relationships": [
"product": [
"data": ["type": "product", "id": "3ab38aae-bbf7-4846-9c32-af9d94bf5ad4"]
]
]
]
],
encoding: JSONEncoding.default
).responseJSON { response in
let json = JSON(data: response.data!)
}
using RestSharp;
 
var client = new RestClient("https://api.keygen.sh/v1/accounts/{ACCOUNT}");
var request = new RestRequest("policies", Method.POST);
 
request.AddHeader("Content-Type", "application/vnd.api+json");
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer {TOKEN}");
 
request.AddJsonBody(new {
data = new {
type = "policies",
attributes = new {
name = "Basic"
},
relationships = new {
product = new {
data = new { type = "product", id = "3ab38aae-bbf7-4846-9c32-af9d94bf5ad4" }
}
}
}
});
 
var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*
 
val body = JSONObject(mapOf(
"data" to mapOf(
"type" to "policies",
"attributes" to mapOf(
"name" to "Basic"
),
"relationships" to mapOf(
"product" to mapOf(
"data" to mapOf(
"type" to "products",
"id" to "3ab38aae-bbf7-4846-9c32-af9d94bf5ad4"
)
)
)
)
))
 
val res = Unirest.post("https://api.keygen.sh/v1/accounts/{ACCOUNT}/policies")
.header("Authorization", "Bearer {TOKEN}")
.header("Content-Type", "application/vnd.api+json")
.header("Accept", "application/vnd.api+json")
.body(body)
.asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;
import org.json.*;
 
import static java.util.Map.ofEntries;
import static java.util.Map.entry;
 
JSONObject body = new JSONObject(ofEntries(
entry("data", ofEntries(
entry("type", "policies"),
entry("attributes", ofEntries(
entry("name", "Basic")
)),
entry("relationships", ofEntries(
entry("product", ofEntries(
entry("data", ofEntries(
entry("type", "products"),
entry("id", "3ab38aae-bbf7-4846-9c32-af9d94bf5ad4")
))
))
))
))
));
 
HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/{ACCOUNT}/policies")
.header("Authorization", "Bearer {TOKEN}")
.header("Content-Type", "application/vnd.api+json")
.header("Accept", "application/vnd.api+json")
.body(body)
.asJson();
#include <iostream>
#include <string>
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
 
using namespace std;
using namespace web;
using namespace web::http;
using namespace web::http::client;
using namespace web::json;
using namespace utility;
 
http_client client("https://api.keygen.sh/v1/accounts/{ACCOUNT}");
http_request req;
 
value attrs;
attrs["name"] = value::string("Basic");
 
value product_;
product_["type"] = value::string("products");
product_["id"] = value::string("3ab38aae-bbf7-4846-9c32-af9d94bf5ad4");
 
value product;
product["data"] = product_;
 
value rels;
rels["product"] = product;
 
value data;
data["type"] = value::string("policies");
data["attributes"] = attrs;
data["relationships"] = rels;
 
value body;
body["data"] = data;
 
req.headers().add("Authorization", "Bearer {TOKEN}");
req.headers().add("Content-Type", "application/vnd.api+json");
req.headers().add("Accept", "application/json");
 
req.set_request_uri("/policies");
req.set_method(methods::POST);
req.set_body(body.serialize());
 
client.request(req)
.then([](http_response res)
{
auto data = res.extract_json().get();
})
.wait();
curl -X POST https://api.keygen.sh/v1/accounts/{ACCOUNT}/policies \
-H 'Content-Type: application/vnd.api+json' \
-H 'Accept: application/vnd.api+json' \
-H 'Authorization: Bearer {TOKEN}' \
-d '{
"data": {
"type": "policies",
"attributes": {
"name": "Basic"
},
"relationships": {
"product": {
"data": { "type": "product", "id": "3ab38aae-bbf7-4846-9c32-af9d94bf5ad4" }
}
}
}
}'

Example response / 201 Created

{
"data": {
"id": "0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
"type": "policies",
"links": {
"self": "/v1/accounts/{ACCOUNT}/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065"
},
"attributes": {
"name": "Basic",
"duration": null,
"strict": false,
"floating": false,
"scheme": null,
"requireProductScope": false,
"requirePolicyScope": false,
"requireMachineScope": false,
"requireFingerprintScope": false,
"requireComponentsScope": false,
"requireUserScope": false,
"requireChecksumScope": false,
"requireVersionScope": false,
"requireCheckIn": false,
"checkInInterval": null,
"checkInIntervalCount": null,
"usePool": false,
"maxMachines": 1,
"maxProcesses": null,
"maxCores": null,
"maxUses": null,
"encrypted": false,
"protected": false,
"requireHeartbeat": false,
"heartbeatDuration": null,
"heartbeatCullStrategy": "DEACTIVATE_DEAD",
"heartbeatResurrectionStrategy": "NO_REVIVE",
"heartbeatBasis": "FROM_FIRST_PING",
"machineUniquenessStrategy": "UNIQUE_PER_LICENSE",
"machineMatchingStrategy": "MATCH_ALL",
"componentUniquenessStrategy": "UNIQUE_PER_MACHINE",
"componentMatchingStrategy": "MATCH_ALL",
"expirationStrategy": "RESTRICT_ACCESS",
"expirationBasis": "FROM_CREATION",
"renewalBasis": "FROM_EXPIRY",
"transferStrategy": "KEEP_EXPIRY",
"authenticationStrategy": "TOKEN",
"leasingStrategy": "PER_MACHINE",
"metadata": {},
"created": "2017-01-02T20:26:53.464Z",
"updated": "2017-01-02T20:26:53.464Z"
},
"relationships": {
"account": {
"links": {
"related": "/v1/accounts/{ACCOUNT}"
},
"data": {
"type": "accounts",
"id": "{ACCOUNT}"
}
},
"product": {
"links": {
"related": "/v1/accounts/{ACCOUNT}/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/product"
},
"data": {
"type": "products",
"id": "3ab38aae-bbf7-4846-9c32-af9d94bf5ad4"
}
},
"pool": {
"links": {
"related": "/v1/accounts/{ACCOUNT}/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/pool"
}
},
"licenses": {
"links": {
"related": "/v1/accounts/{ACCOUNT}/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/licenses"
}
},
"entitlements": {
"links": {
"related": "/v1/accounts/{ACCOUNT}/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements"
}
}
}
}
}

linkRetrieve a policy

Retrieves the details of an existing policy.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to view the resource: either an admin, an environment, or the product it belongs to.

linkURL Parameters

  • link<account>

    stringrequired

    The identifier (UUID) or slug of your Keygen account.

  • link<id>

    stringrequired

    The identifier (UUID) of the policy to be retrieved.

linkReturns

A 200 OK response will be returned along with a policy object.

Upon error, an errors object will be returned along with an HTTP status code indicating the type of error. When an error occurs, the data property will not be included.

Definition

https://api.keygen.sh/v1/accounts/<account>/policies/<id>

Example request

const fetch = require("node-fetch")
 
const response = await fetch("https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065", {
method: "GET",
headers: {
"Accept": "application/vnd.api+json",
"Authorization": "Bearer <token>"
}
})
 
const { data, errors } = await response.json()
import requests
import json
 
res = requests.get(
"https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
headers={
"Accept": "application/vnd.api+json",
"Authorization": "Bearer <token>"
}
).json()
import SwiftyJSON
import Alamofire
 
Alamofire.request("https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
headers: [
"Accept": "application/vnd.api+json",
"Authorization": "Bearer <token>"
]
).responseJSON { response in
let json = JSON(data: response.data!)
}
using RestSharp;
 
var client = new RestClient("https://api.keygen.sh/v1/accounts/<account>");
var request = new RestRequest(
"policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
Method.GET
);
 
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <token>");
 
var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
 
val res = Unirest.get("https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065")
.header("Authorization", "Bearer <token>")
.header("Accept", "application/vnd.api+json")
.asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;
 
HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065")
.header("Authorization", "Bearer <token>")
.header("Accept", "application/vnd.api+json")
.asJson();
#include <iostream>
#include <string>
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
 
using namespace std;
using namespace web;
using namespace web::http;
using namespace web::http::client;
using namespace utility;
 
http_client client("https://api.keygen.sh/v1/accounts/<account>");
http_request req;
 
req.headers().add("Authorization", "Bearer <token>");
req.headers().add("Accept", "application/json");
 
req.set_request_uri("/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065");
req.set_method(methods::GET);
 
client.request(req)
.then([](http_response res) {
auto data = res.extract_json().get();
})
.wait();
curl https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065 \
-H 'Accept: application/vnd.api+json' \
-H 'Authorization: Bearer <token>'

Example response / 200 OK

{
"data": {
"id": "0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
"type": "policies",
"links": {
"self": "/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065"
},
"attributes": {
"name": "Premium Add-On",
"duration": 1209600,
"strict": false,
"floating": true,
"scheme": null,
"requireProductScope": false,
"requirePolicyScope": false,
"requireMachineScope": false,
"requireFingerprintScope": false,
"requireComponentsScope": false,
"requireUserScope": false,
"requireChecksumScope": false,
"requireVersionScope": false,
"requireCheckIn": false,
"checkInInterval": null,
"checkInIntervalCount": null,
"usePool": false,
"maxMachines": 5,
"maxProcesses": null,
"maxCores": null,
"maxUses": null,
"encrypted": false,
"protected": false,
"requireHeartbeat": false,
"heartbeatDuration": null,
"heartbeatCullStrategy": "DEACTIVATE_DEAD",
"machineUniquenessStrategy": "UNIQUE_PER_LICENSE",
"machineMatchingStrategy": "MATCH_ALL",
"componentUniquenessStrategy": "UNIQUE_PER_MACHINE",
"componentMatchingStrategy": "MATCH_ALL",
"expirationStrategy": "RESTRICT_ACCESS",
"expirationBasis": "FROM_CREATION",
"renewalBasis": "FROM_EXPIRY",
"transferStrategy": "KEEP_EXPIRY",
"authenticationStrategy": "TOKEN",
"leasingStrategy": "PER_MACHINE",
"overageStrategy": "NO_OVERAGE",
"metadata": {},
"created": "2017-01-02T20:26:53.464Z",
"updated": "2017-01-02T20:26:53.464Z"
},
"relationships": {
"account": {
"links": {
"related": "/v1/accounts/<account>"
},
"data": {
"type": "accounts",
"id": "<account>"
}
},
"product": {
"links": {
"related": "/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/product"
},
"data": {
"type": "products",
"id": "3ab38aae-bbf7-4846-9c32-af9d94bf5ad4"
}
},
"pool": {
"links": {
"related": "/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/pool"
}
},
"licenses": {
"links": {
"related": "/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/licenses"
}
},
"entitlements": {
"links": {
"related": "/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements"
}
}
}
}
}

linkUpdate a policy

Updates the specified policy resource by setting the values of the parameters passed. Any parameters not provided will be left unchanged.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: either an admin, an environment, or the product it belongs to.

linkURL Parameters

  • link<account>

    stringrequired

    The identifier (UUID) or slug of your Keygen account.

  • link<id>

    stringrequired

    The identifier (UUID) of the policy to be updated.

linkAttributes

  • linkdata.attributes.name

    stringoptional

    The name of the policy.

  • linkdata.attributes.duration

    integeroptional

    The duration for the policy in seconds. When a new license implements the policy, the license's expiry is calculated with this value (i.e. time.now + policy.duration). If null, licenses will never expire. Updating this attribute will not retroactively update previously created licenses.

  • linkdata.attributes.strict

    booleanoptional

    When enabled, a license that implements the policy will be considered invalid if its machine limit, machine core limit, or processes limit is surpassed. In addition, strict requires a license to have at least 1 machine associated with it in order to pass validation.

  • linkdata.attributes.floating

    booleanoptional

    When enabled, a license that implements the policy will be valid across multiple machines. Though this is not enforced i.e. it does not invalidate a license if it's associated with more than 1 machine unless the policy is strict.

  • linkdata.attributes.requireProductScope

    booleanoptional

    When enabled, validating a license that implements the policy will require a product scope that matches the licenses's product relationship by its identifier (UUID).

  • linkdata.attributes.requirePolicyScope

    booleanoptional

    When enabled, validating a license that implements the policy will require a policy scope that matches the licenses's policy relationship by its identifier (UUID).

  • linkdata.attributes.requireMachineScope

    booleanoptional

    When enabled, validating a license that implements the policy will require a machine scope that matches at least 1 of the licenses's machine relationships by its identifier (UUID).

  • linkdata.attributes.requireFingerprintScope

    booleanoptional

    When enabled, validating a license that implements the policy will require a fingerprint scope that matches at least 1 of the licenses's machine relationships by its fingerprint.

  • linkdata.attributes.requireComponentsScope

    booleanoptional

    When enabled, validating a license that implements the policy will require a components scope that matches at least 1 of the licenses's machine components by its fingerprint.

  • linkdata.attributes.requireUserScope

    booleanoptional

    When enabled, validating a license that implements the policy will require a user scope that matches the license's user relationship.

  • linkdata.attributes.requireChecksumScope

    booleanoptional

    When enabled, validating a license that implements the policy will require a checksum scope to be provided, matching an accessible artifact for the license.

  • linkdata.attributes.requireVersionScope

    booleanoptional

    When enabled, validating a license that implements the policy will require a version scope to be provided, matching an accessible release for the license.

  • linkdata.attributes.requireCheckIn

    booleanoptional

    When enabled, a license that implements the policy will require check-in at a predefined interval to continue to pass validation i.e. if a license misses a check-in, it will be invalidated.

  • linkdata.attributes.checkInInterval

    stringoptional

    One of day, week, month or year. The frequency at which a license should check-in.

  • linkdata.attributes.checkInIntervalCount

    integeroptional

    The number of intervals (specified in the check-in interval property) between each required check-in. For example, checkInInterval=week and checkInIntervalCount=2 requires check-in every 2 weeks. Must be a number between 1 and 365 inclusive.

  • linkdata.attributes.maxMachines

    integeroptional

    The maximum number of machines a license implementing the policy can have associated with it. This is only enforced when the policy is strict. When null, an unlimited number of machines may be associated with a license if the policy is floating. Must be a number greater than 0, and must be equal to 1 for non-floating policies.

  • linkdata.attributes.maxProcesses

    integeroptional

    The maximum number of machine processes a license implementing the policy can have associated with it, also depending on the policy's leasing strategy. When null, an unlimited number of machine processes may be associated with a license. Must be a number greater than 0.

  • linkdata.attributes.maxCores

    integeroptional

    The maximum number of machine CPU cores a license implementing the policy can have associated with it. The count is the sum of all cores for the license's machines. This is inherited from the policy. When null, a license which implements the policy can have an unlimited number of CPU cores.

  • linkdata.attributes.maxUses

    integeroptional

    The maximum number of uses a license implementing the policy can have. Cannot exceed 2,147,483,647, which is the maximum value of a 4 byte integer. When null, a license which implements the policy can have an unlimited number of uses.

  • linkdata.attributes.protected

    booleanoptional

    Whether or not the policy is protected. A protected policy disallows users the ability to create licenses themselves, useful in situations where Keygen is only managed server-side.

  • linkdata.attributes.requireHeartbeat

    booleanoptional

    Whether or not the policy requires its machines to maintain a heartbeat. When enabled, machines that do not have a heartbeat will fail validation with a HEARTBEAT_NOT_STARTED validation code. Otherwise, heartbeats are optional.

    Please note: updating a policy from not requiring heartbeats to requiring heartbeats will cause all existing machines without a heartbeat to be considered dead after a short idling period, according to the policy's heartbeat duration. This means that any existing machines MAY be deactivated if they are not already maintaining consistent heartbeat pings.
    Please note: this only applies to machines, not processes. Processes always require a heartbeat.
  • linkdata.attributes.heartbeatDuration

    integeroptional

    The heartbeat duration for the policy, in seconds. When a machine has an active heartbeat monitor, the machine must send heartbeat pings within this timeframe to remain activated. Must be greater than or equal to 1 minute (60).

  • linkdata.attributes.heartbeatCullStrategy

    stringoptional

    The strategy used for culling dead machines and processes.

    Please note: dead machines will not pass license validation. The resulting failed validation code will be HEARTBEAT_DEAD.
    Options
    • DEACTIVATE_DEAD: Automatically deactivate machines that fail to maintain their heartbeat pings. This is the default.
    • KEEP_DEAD: Mark machines that fail to maintain their heartbeat pings as dead, but do not deactivate.
  • linkdata.attributes.heartbeatResurrectionStrategy

    stringoptional

    The strategy used for controlling whether or not dead machines and processes can be resurrected shortly after death. A resurrection occurs when a heartbeat ping is sent to a dead machine or process that is within its resurrection window.

    Please note: dead machines will not pass license validation. The resulting failed validation code will be HEARTBEAT_DEAD.
    Options
    • NO_REVIVE: Do not allow dead machines and processes to be revived. This is the default.
    • 1_MINUTE_REVIVE: A machine or process can be revived if it sends a ping within 1 minute from its time of death.
    • 2_MINUTE_REVIVE: A machine or process can be revived if it sends a ping within 2 minutes from its time of death.
    • 5_MINUTE_REVIVE: A machine or process can be revived if it sends a ping within 5 minutes from its time of death.
    • 10_MINUTE_REVIVE: A machine or process can be revived if it sends a ping within 10 minutes from its time of death.
    • 15_MINUTE_REVIVE: A machine or process can be revived if it sends a ping within 15 minutes from its time of death.
    • ALWAYS_REVIVE: A machine or process can always be revived. Requires a cull strategy of KEEP_DEAD.
  • linkdata.attributes.heartbeatBasis

    stringoptional

    Control when a machine's initial heartbeat is started. By default, a machine's heartbeat is started on creation when its policy requires a heartbeat. Overwise, it is started on first ping.

    Please note: this only applies to machines, not processes. Processes always have a heartbeat basis of FROM_CREATION, because their heartbeat is required.
    Options
    • FROM_CREATION: Machine heartbeat is started immediately upon creation.
    • FROM_FIRST_PING: Mahine heartbeat is started after their first heartbeat ping event.
  • linkdata.attributes.machineUniquenessStrategy

    stringoptional

    The uniqueness validation strategy for machine fingerprints. You can utilize this to prevent duplicate fingerprints across a variety of scopes.

    This can be especially useful for disallowing trial licenses for a specific machine (i.e. device) that had previously completed a trial evaluation using another trial license. You would set the trial policy to UNIQUE_PER_POLICY, and then set any non-trial policies to UNIQUE_PER_LICENSE. This would effectively block a machine from using multiple trial licenses, while still allowing the machine to be associated with non-trial licenses.
    Options
    • UNIQUE_PER_ACCOUNT: Machine fingerprints must be unique across the entire Keygen account. This will block all duplicate fingerprints, regardless of whether or not the fingerprint belongs to another product, policy or license.
    • UNIQUE_PER_PRODUCT: Machine fingerprints must be unique across all licenses belonging to a product. This will block all duplicate fingerprints of the same product, regardless of whether or not the fingerprint belongs to another policy or license.
    • UNIQUE_PER_POLICY: Machine fingerprints must be unique across all licenses for the policy. This will block all duplicate fingerprints of the same policy, regardless of whether or not the fingerprint belongs to another license.
    • UNIQUE_PER_LICENSE: Machine fingerprints must be unique to the license. This will block all duplicate fingerprints for same license, but the same fingerprint can exist across different licenses. This is the default.
  • linkdata.attributes.machineMatchingStrategy

    stringoptional

    The matching strategy for machine fingerprints supplied during a license validation.

    Options
    • MATCH_ANY: At least 1 of the supplied fingerprints must match a fingerprint for the license's associated machines. E.g. if 3 fingerprints are supplied, at least 1 of them must match.
    • MATCH_TWO: At least 2 of the supplied fingerprints must match a fingerprint for the license's associated machines. E.g. if 4 fingerprints are supplied, at least 2 of them must match.
    • MATCH_MOST: The majority of supplied fingerprints must match the fingerprints for the license's associated machines. E.g. if 3 fingerprints are supplied, at least 2 of them must match.
    • MATCH_ALL: All supplied fingerprints must match the fingerprints for the license's associated machines. E.g. if 3 fingerprints are supplied, all 3 of them must match.
  • linkdata.attributes.componentUniquenessStrategy

    stringoptional

    The uniqueness validation strategy for component fingerprints. You can utilize this to prevent duplicate fingerprints across a variety of scopes.

    This is especially useful for disallowing trial licenses for specific hardware that had previously completed a trial evaluation using another trial machine or license. You would set the trial policy to UNIQUE_PER_POLICY, and then set any non-trial policies to UNIQUE_PER_LICENSE. This would effectively block a device from using multiple trials even if e.g. the operating system was reinstalled.
    Options
    • UNIQUE_PER_ACCOUNT: Component fingerprints must be unique across the entire Keygen account. This will block all duplicate fingerprints, regardless of whether or not the fingerprint belongs to another product, policy or license.
    • UNIQUE_PER_PRODUCT: Component fingerprints must be unique across all licenses belonging to a product. This will block all duplicate fingerprints of the same product, regardless of whether or not the fingerprint belongs to another policy or license.
    • UNIQUE_PER_POLICY: Component fingerprints must be unique across all licenses for the policy. This will block all duplicate fingerprints of the same policy, regardless of whether or not the fingerprint belongs to another license.
    • UNIQUE_PER_LICENSE: Component fingerprints must also be unique to the license. This will block all duplicate fingerprints for same license, but the same fingerprint can exist across different licenses.
    • UNIQUE_PER_MACHINE: Component fingerprints must be unique to the machine. This will allow the same component to exist across multiple machines for the same license. This is the default.
  • linkdata.attributes.componentMatchingStrategy

    stringoptional

    The matching strategy for component fingerprints supplied during a license validation.

    This is especially useful for managing individual hardware components of a given device, e.g. HDD ID, mobo ID, MAC addresses, IP addresses, etc., and then requiring that some, most, or all components match during a license validation. These can be managed through the components resource.
    Options
    • MATCH_ANY: At least 1 of the supplied fingerprints must match a fingerprint for the machine's associated components. E.g. if 3 fingerprints are supplied, at least 1 of them must match.
    • MATCH_TWO: At least 2 of the supplied fingerprints must match a fingerprint for the machine's associated components. E.g. if 4 fingerprints are supplied, at least 2 of them must match.
    • MATCH_MOST: The majority of supplied fingerprints must match the fingerprints for the machine's associated components. E.g. if 3 fingerprints are supplied, at least 2 of them must match.
    • MATCH_ALL: All supplied fingerprints must match the fingerprints for the machine's associated components. E.g. if 3 fingerprints are supplied, all 3 of them must match.
  • linkdata.attributes.expirationStrategy

    stringoptional

    The strategy for expired licenses during a license validation and when accessing releases.

    Options
    • RESTRICT_ACCESS: Expired licenses can continue to access releases published prior to their expiry, but automatic upgrades are disabled. Validation scopes take precedence over expiry check during license validation.
    • REVOKE_ACCESS: Expired licenses are no longer able to access any releases, including past releases and upgrades. Expiry check takes precedence over scopes during license validation.
    • MAINTAIN_ACCESS: Expired licenses can continue to access releases published prior to their expiry, but automatic upgrades are disabled. Validation scopes take precedence over expiry check during license validation. In addition, validations with an EXPIRED code will return valid=true.
    • ALLOW_ACCESS: Expired licenses can access any releases, including past releases and future automatic upgrades. Validation scopes take precedence over expiry check during license validation. In addition, validations with an EXPIRED code will return valid=true.
  • linkdata.attributes.expirationBasis

    stringoptional

    Control when a license's initial expiry is set. By default, a license's expiration date is set on creation.

    Options
    • FROM_CREATION: License expirations are set immediately upon creation.
    • FROM_FIRST_VALIDATION: License expirations are set after their first license validation event.
    • FROM_FIRST_ACTIVATION: License expirations are set after their first machine activation event.
    • FROM_FIRST_DOWNLOAD: License expirations are set after their first release download event.
    • FROM_FIRST_USE: License expirations are set after their first usage increment event.
      Note: "usage" is not activation or validation.FROM_FIRST_USE is for a license's usage.
  • linkdata.attributes.renewalBasis

    stringoptional

    Control how a license's expiry is extended during renewal. For example, you may want to extend the license's expiry from the current time, instead of from the license's current expiry value.

    Options
    • FROM_EXPIRY: License expiry is extended from the license's current expiry value, i.e. license.expiry = license.expiry + policy.duration. This is the default.
    • FROM_NOW: License expiry is extended from the current time, i.e. license.expiry = time.now + policy.duration.
  • linkdata.attributes.transferStrategy

    stringoptional

    Control whether a license's expiration is reset when transferred to this policy.

    This is especially useful when transferring a license from a policy with a short duration to one with a longer duration. For example, upgrading from a 14 day free trial license to a yearly license.
    Options
    • RESET_EXPIRY: Reset the transferred license's expiry from the time of transfer. For example, if the license had an expiry 3 months from now, and the new policy has a duration of 1 year, transferring would reset the expiry to 1 year from the time of transfer. When the policy has no duration, the license's expiry is removed.
    • KEEP_EXPIRY: Do not change the license's current expiry. This is the default.
  • linkdata.attributes.authenticationStrategy

    stringoptional

    The strategy used for authenticating as a license, for client-side integrations.

    Options
    • TOKEN: Allow licenses to authenticate using a license token. This is the default.
    • LICENSE: Allow licenses to authenticate using a license key.
    • MIXED: Allow both license token and license key authentication (each covered above).
    • NONE: Disable the ability for licenses to authenticate with the API.
  • linkdata.attributes.leasingStrategy

    stringoptional

    The strategy used for leasing machine processes.

    This defines how processes are leased and counted. For example, a PER_MACHINE leasing strategy would count processes per-machine, meaning if a policy allowed up to 5 processes, it would allow a license with 2 machines, 5 processes each; similarly, with a PER_LICENSE leasing strategy, processes are counted collectively across all of a license's machines, meaning a license will not be able to create 10 processes across 2 machines, because the sum of processes would be over their limit of 5 processes per-license.
    Options
    • PER_MACHINE: Machine processes are counted per-machine, i.e. limits are enforced individually for each machine. This is the default.
    • PER_LICENSE: Machine processes are counted per-license, i.e. collectively across all of a license's machines.
  • linkdata.attributes.overageStrategy

    stringoptional

    The strategy used for allowing machine, core and process overages. Set to NO_OVERAGE to disable overages altogether (attempts to exceed a limit will then result in an error).

    This defines an overage allowance for a license. This allowance effects a license's machine limit, machine core limit, and its machine process limit. Giving a license an overage allowance may be beneficial in environments where rolling restarts of the application are common, or another situation where overages are expected. This lets you allow overages, bounded and unbounded, while handling the unique validation codes to ensure total license compliance.
    Options
    • ALWAYS_ALLOW_OVERAGE: The license may exceed its limits, and doing so will not effect the licenses validity, i.e. the following validation codes will return valid=true: TOO_MANY_MACHINES, TOO_MANY_CORES, TOO_MANY_PROCESSES.
    • ALLOW_1_25X_OVERAGE: The license may exceed its limits, up to a maximum of 1.25x. Exceeding a limit will not effect the license's validity right away, i.e. the following validation codes will return valid=true: TOO_MANY_MACHINES, TOO_MANY_CORES, TOO_MANY_PROCESSES. The license will begin to fail validation once the 1.25x allowance has been exceeded. When using a 1.25x allowance, all resource limits must be divisible by 4.
    • ALLOW_1_5X_OVERAGE: The license may exceed its limits, up to a maximum of 1.5x. Exceeding a limit will not effect the license's validity right away, i.e. the following validation codes will return valid=true: TOO_MANY_MACHINES, TOO_MANY_CORES, TOO_MANY_PROCESSES. The license will begin to fail validation once the 1.5x allowance has been exceeded. When using a 1.5x allowance, all resource limits must be divisible by 2.
    • ALLOW_2X_OVERAGE: The license may exceed its limits, up to a maximum of 2x. Exceeding a limit will not effect the license's validity right away, i.e. the following validation codes will return valid=true: TOO_MANY_MACHINES, TOO_MANY_CORES, TOO_MANY_PROCESSES. The license will begin to fail validation once the 2x allowance has been exceeded.
    • NO_OVERAGE: Do not allow overages. Attempts to exceed limits will fail. This is the default.
  • linkdata.attributes.metadata

    object<string, any>optional

    Object containing policy metadata.

linkReturns

A 200 OK response will be returned along with the updated policy object.

Upon error, an errors object will be returned along with an HTTP status code indicating the type of error. When an error occurs, the data property will not be included.

Definition

https://api.keygen.sh/v1/accounts/<account>/policies/<id>

Example request

const fetch = require("node-fetch")
 
const response = await fetch("https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065", {
method: "PATCH",
headers: {
"Content-Type": "application/vnd.api+json",
"Accept": "application/vnd.api+json",
"Authorization": "Bearer <token>"
},
body: JSON.stringify({
"data": {
"type": "policies",
"attributes": {
"maxMachines": 15
}
}
})
})
 
const { data, errors } = await response.json()
import requests
import json
 
res = requests.patch(
"https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
headers={
"Content-Type": "application/vnd.api+json",
"Accept": "application/vnd.api+json",
"Authorization": "Bearer <token>"
},
data=json.dumps({
"data": {
"type": "policies",
"attributes": {
"maxMachines": 15
}
}
})
).json()
import SwiftyJSON
import Alamofire
 
Alamofire.request("https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
method: .patch,
headers: [
"Content-Type": "application/vnd.api+json",
"Accept": "application/vnd.api+json",
"Authorization": "Bearer <token>"
],
parameters: [
"data": [
"type": "policies",
"attributes": [
"maxMachines": 15
]
]
],
encoding: JSONEncoding.default
).responseJSON { response in
let json = JSON(data: response.data!)
}
using RestSharp;
 
var client = new RestClient("https://api.keygen.sh/v1/accounts/<account>");
var request = new RestRequest(
"policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
Method.PATCH
);
 
request.AddHeader("Content-Type", "application/vnd.api+json");
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <token>");
 
request.AddJsonBody(new {
data = new {
type = "policies",
attributes = new {
maxMachines = 15
}
}
});
 
var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*
 
val body = JSONObject(mapOf(
"data" to mapOf(
"type" to "policies",
"attributes" to mapOf(
"maxMachines" to 15
)
)
))
 
val res = Unirest.patch("https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/vnd.api+json")
.header("Accept", "application/vnd.api+json")
.body(body)
.asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;
import org.json.*;
 
import static java.util.Map.ofEntries;
import static java.util.Map.entry;
 
JSONObject body = new JSONObject(ofEntries(
entry("data", ofEntries(
entry("type", "policies"),
entry("attributes", ofEntries(
entry("maxMachines", 15)
))
))
));
 
HttpResponse<JsonNode> res = Unirest.patch("https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/vnd.api+json")
.header("Accept", "application/vnd.api+json")
.body(body)
.asJson();
#include <iostream>
#include <string>
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
 
using namespace std;
using namespace web;
using namespace web::http;
using namespace web::http::client;
using namespace web::json;
using namespace utility;
 
http_client client("https://api.keygen.sh/v1/accounts/<account>");
http_request req;
 
value attrs;
attrs["maxMachines"] = value::number(15);
 
value data;
data["type"] = value::string("policies");
data["attributes"] = attrs;
 
value body;
body["data"] = data;
 
req.headers().add("Authorization", "Bearer <token>");
req.headers().add("Content-Type", "application/vnd.api+json");
req.headers().add("Accept", "application/json");
 
req.set_request_uri("/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065");
req.set_method(methods::PATCH);
req.set_body(body.serialize());
 
client.request(req)
.then([](http_response res)
{
auto data = res.extract_json().get();
})
.wait();
curl -X PATCH https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065 \
-H 'Content-Type: application/vnd.api+json' \
-H 'Accept: application/vnd.api+json' \
-H 'Authorization: Bearer <token>' \
-d '{
"data": {
"type": "policies",
"attributes": {
"maxMachines": 15
}
}
}'

Example response / 200 OK

{
"data": {
"id": "0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
"type": "policies",
"links": {
"self": "/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065"
},
"attributes": {
"name": "Premium Add-On",
"duration": 1209600,
"strict": false,
"floating": true,
"scheme": null,
"requireProductScope": false,
"requirePolicyScope": false,
"requireMachineScope": false,
"requireFingerprintScope": false,
"requireComponentsScope": false,
"requireUserScope": false,
"requireChecksumScope": false,
"requireVersionScope": false,
"requireCheckIn": false,
"checkInInterval": null,
"checkInIntervalCount": null,
"usePool": false,
"maxMachines": 15,
"maxProcesses": null,
"maxCores": null,
"maxUses": null,
"encrypted": false,
"protected": false,
"requireHeartbeat": false,
"heartbeatDuration": null,
"heartbeatCullStrategy": "DEACTIVATE_DEAD",
"heartbeatResurrectionStrategy": "NO_REVIVE",
"heartbeatBasis": "FROM_FIRST_PING",
"machineUniquenessStrategy": "UNIQUE_PER_LICENSE",
"machineMatchingStrategy": "MATCH_ALL",
"componentUniquenessStrategy": "UNIQUE_PER_MACHINE",
"componentMatchingStrategy": "MATCH_ALL",
"expirationStrategy": "RESTRICT_ACCESS",
"expirationBasis": "FROM_CREATION",
"renewalBasis": "FROM_EXPIRY",
"transferStrategy": "KEEP_EXPIRY",
"authenticationStrategy": "TOKEN",
"leasingStrategy": "PER_MACHINE",
"metadata": {},
"created": "2017-01-02T20:26:53.464Z",
"updated": "2017-01-02T20:26:53.464Z"
},
"relationships": {
"account": {
"links": {
"related": "/v1/accounts/<account>"
},
"data": {
"type": "accounts",
"id": "<account>"
}
},
"product": {
"links": {
"related": "/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/product"
},
"data": {
"type": "products",
"id": "3ab38aae-bbf7-4846-9c32-af9d94bf5ad4"
}
},
"pool": {
"links": {
"related": "/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/pool"
}
},
"licenses": {
"links": {
"related": "/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/licenses"
}
},
"entitlements": {
"links": {
"related": "/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements"
}
}
}
}
}

linkDelete a policy

Permanently deletes a policy. It cannot be undone. This action also immediately deletes any licenses that the policy is associated with.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: either an admin, an environment, or the product it belongs to.

linkURL Parameters

  • link<account>

    stringrequired

    The identifier (UUID) or slug of your Keygen account.

  • link<id>

    stringrequired

    The identifier (UUID) of the policy to be deleted.

linkReturns

A 204 No Content response will be returned.

Upon error, an errors object will be returned along with an HTTP status code indicating the type of error. When an error occurs, the data property will not be included.

Definition

https://api.keygen.sh/v1/accounts/<account>/policies/<id>

Example request

const fetch = require("node-fetch")
 
const response = await fetch("https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065", {
method: "DELETE",
headers: {
"Accept": "application/vnd.api+json",
"Authorization": "Bearer <token>"
}
})
import requests
 
res = requests.delete(
"https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
headers={
"Accept": "application/vnd.api+json",
"Authorization": "Bearer <token>"
}
)
import SwiftyJSON
import Alamofire
 
Alamofire.request("https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
method: .delete,
headers: [
"Accept": "application/vnd.api+json",
"Authorization": "Bearer <token>"
]
).responseJSON { response in
let status = response.response?.statusCode
}
using RestSharp;
 
var client = new RestClient("https://api.keygen.sh/v1/accounts/<account>");
var request = new RestRequest(
"policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
Method.DELETE
);
 
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <token>");
 
var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
 
val res = Unirest.delete("https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065")
.header("Authorization", "Bearer <token>")
.header("Accept", "application/vnd.api+json")
.asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;
 
HttpResponse<JsonNode> res = Unirest.delete("https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065")
.header("Authorization", "Bearer <token>")
.header("Accept", "application/vnd.api+json")
.asJson();
#include <iostream>
#include <string>
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
 
using namespace std;
using namespace web;
using namespace web::http;
using namespace web::http::client;
using namespace utility;
 
http_client client("https://api.keygen.sh/v1/accounts/<account>");
http_request req;
 
req.headers().add("Authorization", "Bearer <token>");
req.headers().add("Accept", "application/json");
 
req.set_request_uri("/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065");
req.set_method(methods::DELETE);
 
client.request(req)
.then([](http_response res) {
auto status = res.status_code();
})
.wait();
curl -X DELETE https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065 \
-H 'Accept: application/vnd.api+json' \
-H 'Authorization: Bearer <token>'

Example response / 204 No Content

No content

linkList all policies

Returns a list of policies. The policies are returned sorted by creation date, with the most recent policies appearing first. Resources are automatically scoped to the authenticated bearer e.g. when authenticated as a product, only policies of that specific product will be listed.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to view the resources: either an admin or a product.

linkURL Parameters

  • link<account>

    stringrequired

    The identifier (UUID) or slug of your Keygen account.

linkQuery Parameters

  • linklimit

    integerdefault=10

    A limit on the number of policies to be returned. Limit must be a number between 1 and 100.

    /v1/accounts/<account>/policies?limit=25
  • linkpage

    object<string, integer>

    Object containing page size and page number. Page size must be a number between 1 and 100.

    /v1/accounts/<account>/policies?page[size]=15&page[number]=2
  • linkproduct

    string

    The identifier (UUID) of the product to filter by.

    /v1/accounts/<account>/policies?product=3ab38aae-bbf7-4846-9c32-af9d94bf5ad4

linkReturns

A 200 OK response will be returned along with a list of policy objects.

Upon error, an errors object will be returned along with an HTTP status code indicating the type of error. When an error occurs, the data property will not be included.

Definition

https://api.keygen.sh/v1/accounts/<account>/policies

Example request

const fetch = require("node-fetch")
 
const response = await fetch("https://api.keygen.sh/v1/accounts/<account>/policies?limit=15", {
method: "GET",
headers: {
"Accept": "application/vnd.api+json",
"Authorization": "Bearer <token>"
}
})
 
const { data, errors } = await response.json()
import requests
import json
 
res = requests.get(
"https://api.keygen.sh/v1/accounts/<account>/policies?limit=15",
headers={
"Accept": "application/vnd.api+json",
"Authorization": "Bearer <token>"
}
).json()
import SwiftyJSON
import Alamofire
 
Alamofire.request("https://api.keygen.sh/v1/accounts/<account>/policies?limit=15",
headers: [
"Accept": "application/vnd.api+json",
"Authorization": "Bearer <token>"
]
).responseJSON { response in
let json = JSON(data: response.data!)
}
using RestSharp;
 
var client = new RestClient("https://api.keygen.sh/v1/accounts/<account>");
var request = new RestRequest("policies", Method.GET);
 
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <token>");
 
request.AddParameter("limit", 15);
 
var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
 
val res = Unirest.get("https://api.keygen.sh/v1/accounts/<account>/policies")
.header("Authorization", "Bearer <token>")
.header("Accept", "application/vnd.api+json")
.queryString("limit", 15)
.asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;
 
HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<account>/policies")
.header("Authorization", "Bearer <token>")
.header("Accept", "application/vnd.api+json")
.queryString("limit", 15)
.asJson();
#include <iostream>
#include <string>
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
 
using namespace std;
using namespace web;
using namespace web::http;
using namespace web::http::client;
using namespace utility;
 
http_client client("https://api.keygen.sh/v1/accounts/<account>");
http_request req;
 
req.headers().add("Authorization", "Bearer <token>");
req.headers().add("Accept", "application/json");
 
uri_builder uri("/policies");
uri.append_query("limit", 15);
 
req.set_request_uri(uri.to_uri());
req.set_method(methods::GET);
 
client.request(req)
.then([](http_response res) {
auto data = res.extract_json().get();
})
.wait();
curl https://api.keygen.sh/v1/accounts/<account>/policies?limit=15 -g \
-H 'Accept: application/vnd.api+json' \
-H 'Authorization: Bearer <token>'

Example response / 200 OK

{
"data": [
{
"id": "0b4b1a9a-e25a-4f14-a95e-d9dd378d6065",
"type": "policies",
"links": {
"self": "/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065"
},
"attributes": {
"name": "Premium Add-On",
"duration": 1209600,
"strict": false,
"floating": true,
"scheme": null,
"requireProductScope": false,
"requirePolicyScope": false,
"requireMachineScope": false,
"requireFingerprintScope": false,
"requireComponentsScope": false,
"requireUserScope": false,
"requireChecksumScope": false,
"requireVersionScope": false,
"requireCheckIn": false,
"checkInInterval": null,
"checkInIntervalCount": null,
"usePool": false,
"maxMachines": 5,
"maxProcesses": null,
"maxCores": null,
"maxUses": null,
"encrypted": false,
"protected": false,
"requireHeartbeat": false,
"heartbeatDuration": null,
"heartbeatCullStrategy": "DEACTIVATE_DEAD",
"heartbeatResurrectionStrategy": "NO_REVIVE",
"heartbeatBasis": "FROM_FIRST_PING",
"machineUniquenessStrategy": "UNIQUE_PER_LICENSE",
"machineMatchingStrategy": "MATCH_ALL",
"componentUniquenessStrategy": "UNIQUE_PER_MACHINE",
"componentMatchingStrategy": "MATCH_ALL",
"expirationStrategy": "RESTRICT_ACCESS",
"expirationBasis": "FROM_CREATION",
"renewalBasis": "FROM_EXPIRY",
"transferStrategy": "KEEP_EXPIRY",
"authenticationStrategy": "TOKEN",
"leasingStrategy": "PER_MACHINE",
"overageStrategy": "NO_OVERAGE",
"metadata": {},
"created": "2017-01-02T20:26:53.464Z",
"updated": "2017-01-02T20:26:53.464Z"
},
"relationships": {
"account": {
"links": {
"related": "/v1/accounts/<account>"
},
"data": {
"type": "accounts",
"id": "<account>"
}
},
"product": {
"links": {
"related": "/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/product"
},
"data": {
"type": "products",
"id": "3ab38aae-bbf7-4846-9c32-af9d94bf5ad4"
}
},
"pool": {
"links": {
"related": "/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/pool"
}
},
"licenses": {
"links": {
"related": "/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/licenses"
}
},
"entitlements": {
"links": {
"related": "/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements"
}
}
}
},
]
}

linkPop key from pool

Pop off (delete) a key from the policy's pool of pre-determined keys. The returned key is only available directly after a pop, similar to authentication tokens. This cannot be undone.

This action does not create a license resource. What you do with the key after a pop is up to you e.g. create a license with it, discard it, etc. To pop a key and create a license in a single action, simply create a license that implements the pooled policy.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: either an admin, an environment, or the product it belongs to.

linkURL Parameters

  • link<account>

    stringrequired

    The identifier (UUID) or slug of your Keygen account.

  • link<id>

    stringrequired

    The identifier (UUID) of the policy to be retrieved.

linkReturns

A 200 OK response will be returned along with the popped key object.

Upon error, an errors object will be returned along with an HTTP status code indicating the type of error. When an error occurs, the data property will not be included.

Definition

https://api.keygen.sh/v1/accounts/<account>/policies/<id>/pool

Example request

const fetch = require("node-fetch")
 
const response = await fetch("https://api.keygen.sh/v1/accounts/<account>/policies/a5a154d2-f026-40fa-bc8d-a7e3ca415298/pool", {
method: "DELETE",
headers: {
"Accept": "application/vnd.api+json",
"Authorization": "Bearer <token>"
}
})
 
const { data, errors } = await response.json()
import requests
import json
 
res = requests.delete(
"https://api.keygen.sh/v1/accounts/<account>/policies/a5a154d2-f026-40fa-bc8d-a7e3ca415298/pool",
headers={
"Accept": "application/vnd.api+json",
"Authorization": "Bearer <token>"
}
).json()
import SwiftyJSON
import Alamofire
 
Alamofire.request("https://api.keygen.sh/v1/accounts/<account>/policies/a5a154d2-f026-40fa-bc8d-a7e3ca415298/pool",
method: .delete,
headers: [
"Accept": "application/vnd.api+json",
"Authorization": "Bearer <token>"
]
).responseJSON { response in
let json = JSON(data: response.data!)
}
using RestSharp;
 
var client = new RestClient("https://api.keygen.sh/v1/accounts/<account>");
var request = new RestRequest(
"policies/a5a154d2-f026-40fa-bc8d-a7e3ca415298/pool",
Method.DELETE
);
 
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <token>");
 
var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
 
val res = Unirest.delete("https://api.keygen.sh/v1/accounts/<account>/policies/a5a154d2-f026-40fa-bc8d-a7e3ca415298/pool")
.header("Authorization", "Bearer <token>")
.header("Accept", "application/vnd.api+json")
.asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;
 
HttpResponse<JsonNode> res = Unirest.delete("https://api.keygen.sh/v1/accounts/<account>/policies/a5a154d2-f026-40fa-bc8d-a7e3ca415298/pool")
.header("Authorization", "Bearer <token>")
.header("Accept", "application/vnd.api+json")
.asJson();
#include <iostream>
#include <string>
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
 
using namespace std;
using namespace web;
using namespace web::http;
using namespace web::http::client;
using namespace utility;
 
http_client client("https://api.keygen.sh/v1/accounts/<account>");
http_request req;
 
req.headers().add("Authorization", "Bearer <token>");
req.headers().add("Accept", "application/json");
 
req.set_request_uri("/policies/a5a154d2-f026-40fa-bc8d-a7e3ca415298/pool");
req.set_method(methods::DELETE);
 
client.request(req)
.then([](http_response res) {
auto data = res.extract_json().get();
})
.wait();
curl -X DELETE https://api.keygen.sh/v1/accounts/<account>/policies/a5a154d2-f026-40fa-bc8d-a7e3ca415298/pool \
-H 'Accept: application/vnd.api+json' \
-H 'Authorization: Bearer <token>'

Example response / 200 OK

{
"data": {
"id": "6331bcae-73c1-4a7e-bf02-bbf77cbb81d7",
"type": "keys",
"links": {
"self": "/v1/accounts/<account>/keys/6331bcae-73c1-4a7e-bf02-bbf77cbb81d7"
},
"attributes": {
"key": "C1B6DE-39A6E3-DE1529-8559A0-4AF593-V3",
"created": "2017-01-02T20:26:53.464Z",
"updated": "2017-01-02T20:26:53.464Z"
},
"relationships": {
"account": {
"links": {
"related": "/v1/accounts/<account>"
},
"data": {
"type": "accounts",
"id": "<account>"
}
},
"product": {
"links": {
"related": "/v1/accounts/<account>/policies/a5a154d2-f026-40fa-bc8d-a7e3ca415298/pool/product"
},
"data": {
"type": "products",
"id": "1f286fb6-c9bb-498b-a4e7-6c67748b1f4f"
}
},
"policy": {
"links": {
"related": "/v1/accounts/<account>/policies/a5a154d2-f026-40fa-bc8d-a7e3ca415298/pool/policy"
},
"data": {
"type": "policies",
"id": "a5a154d2-f026-40fa-bc8d-a7e3ca415298"
}
}
}
}
}

linkPolicy relationships

Relationship endpoints for the policy resource.

linkAttach policy entitlements

Attach entitlements to a policy. This will immediately be taken into effect for all future license validations. Any license that implements the given policy will automatically possess all the policy's entitlements.

Below are the limitations to attaching an entitlement:

  • You cannot attach an already attached entitlement.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: either an admin, an environment, or the product it belongs to.

linkURL Parameters

  • link<account>

    stringrequired

    The identifier (UUID) or slug of your Keygen account.

  • link<id>

    stringrequired

    The identifier (UUID) of the policy to be updated.

linkReturns

A 201 Created response will be returned along with an array of policy entitlement objects.

Upon error, an errors object will be returned along with an HTTP status code indicating the type of error. When an error occurs, the data property will not be included.

Definition

https://api.keygen.sh/v1/accounts/<account>/policies/<id>/entitlements

Example request

const fetch = require("node-fetch")
 
const response = await fetch("https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements", {
method: "POST",
headers: {
"Content-Type": "application/vnd.api+json",
"Accept": "application/vnd.api+json",
"Authorization": "Bearer <token>"
},
body: JSON.stringify({
"data": [
{
"type": "entitlements",
"id": "57f1ceb4-6bf4-44dd-8967-de88364bf9eb"
}
]
})
})
 
const { data, errors } = await response.json()
import requests
import json
 
res = requests.post(
"https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements",
headers={
"Content-Type": "application/vnd.api+json",
"Accept": "application/vnd.api+json",
"Authorization": "Bearer <token>"
},
data=json.dumps({
"data": [
{
"type": "entitlements",
"id": "57f1ceb4-6bf4-44dd-8967-de88364bf9eb"
}
]
})
).json()
import SwiftyJSON
import Alamofire
 
Alamofire.request("https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements",
method: .post,
headers: [
"Content-Type": "application/vnd.api+json",
"Accept": "application/vnd.api+json",
"Authorization": "Bearer <token>"
],
parameters: [
"data": [
[
"type": "entitlements",
"id": "57f1ceb4-6bf4-44dd-8967-de88364bf9eb"
]
]
],
encoding: JSONEncoding.default
).responseJSON { response in
let json = JSON(data: response.data!)
}
using RestSharp;
 
var client = new RestClient("https://api.keygen.sh/v1/accounts/<account>");
var request = new RestRequest(
"policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements",
Method.POST
);
 
request.AddHeader("Content-Type", "application/vnd.api+json");
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <token>");
 
request.AddJsonBody(new {
data = [
new {
type = "entitlements",
id = "57f1ceb4-6bf4-44dd-8967-de88364bf9eb"
}
]
});
 
var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*
 
val body = JSONObject(mapOf(
"data" to listOf(
mapOf(
"type" to "entitlements",
"id" to "57f1ceb4-6bf4-44dd-8967-de88364bf9eb"
)
)
))
 
val res = Unirest.post("https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/vnd.api+json")
.header("Accept", "application/vnd.api+json")
.body(body)
.asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;
import org.json.*;
 
import static java.util.Map.ofEntries;
import static java.util.Map.entry;
import static java.util.List.of;
 
JSONObject body = new JSONObject(ofEntries(
entry("data", of(
ofEntries(
entry("type", "entitlements"),
entry("id", "57f1ceb4-6bf4-44dd-8967-de88364bf9eb")
)
))
));
 
HttpResponse<JsonNode> res = Unirest.post("https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/vnd.api+json")
.header("Accept", "application/vnd.api+json")
.body(body)
.asJson();
#include <iostream>
#include <string>
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
 
using namespace std;
using namespace web;
using namespace web::http;
using namespace web::http::client;
using namespace web::json;
using namespace utility;
 
http_client client("https://api.keygen.sh/v1/accounts/<account>");
http_request req;
 
value entl;
entl["type"] = value::string("entitlements");
entl["id"] = value::string("57f1ceb4-6bf4-44dd-8967-de88364bf9eb");
 
value data = value::array(1);
data[0] = entl;
 
value body;
body["data"] = data;
 
req.headers().add("Authorization", "Bearer <token>");
req.headers().add("Content-Type", "application/vnd.api+json");
req.headers().add("Accept", "application/json");
 
req.set_request_uri("/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements");
req.set_method(methods::POST);
req.set_body(body.serialize());
 
client.request(req)
.then([](http_response res)
{
auto data = res.extract_json().get();
})
.wait();
curl -X POST https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements \
-H 'Content-Type: application/vnd.api+json' \
-H 'Accept: application/vnd.api+json' \
-H 'Authorization: Bearer <token>' \
-d '{
"data": [
{
"type": "entitlements",
"id": "57f1ceb4-6bf4-44dd-8967-de88364bf9eb"
}
]
}'

Example response / 201 Created

{
"data": [
{
"id": "14fb3e6a-2b30-42b4-b2ff-06ca2e6c0608",
"type": "policy-entitlements",
"attributes": {
"created": "2017-01-02T20:26:53.464Z",
"updated": "2017-01-02T20:26:53.464Z"
},
"relationships": {
"account": {
"links": {
"related": "/v1/accounts/<account>"
},
"data": {
"type": "accounts",
"id": "<account>"
}
},
"entitlement": {
"links": {
"related": "/v1/accounts/<account>/entitlements/57f1ceb4-6bf4-44dd-8967-de88364bf9eb"
},
"data": {
"type": "entitlements",
"id": "57f1ceb4-6bf4-44dd-8967-de88364bf9eb"
}
},
"policy": {
"links": {
"related": "/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065"
},
"data": {
"type": "policies",
"id": "0b4b1a9a-e25a-4f14-a95e-d9dd378d6065"
}
}
},
"links": {
"related": "/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements/57f1ceb4-6bf4-44dd-8967-de88364bf9eb"
}
}
]
}

linkDetach policy entitlements

Detach entitlements from a policy. This will immediately be taken into effect for all future license validations.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to manage the resource: either an admin, an environment, or the product it belongs to.

linkURL Parameters

  • link<account>

    stringrequired

    The identifier (UUID) or slug of your Keygen account.

  • link<id>

    stringrequired

    The identifier (UUID) of the policy to be updated.

linkReturns

A 204 No Content response will be returned.

Upon error, an errors object will be returned along with an HTTP status code indicating the type of error. When an error occurs, the data property will not be included.

Definition

https://api.keygen.sh/v1/accounts/<account>/policies/<id>/entitlements

Example request

const fetch = require("node-fetch")
 
const response = await fetch("https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements", {
method: "DELETE",
headers: {
"Content-Type": "application/vnd.api+json",
"Accept": "application/vnd.api+json",
"Authorization": "Bearer <token>"
},
body: JSON.stringify({
"data": [
{
"type": "entitlements",
"id": "57f1ceb4-6bf4-44dd-8967-de88364bf9eb"
}
]
})
})
 
const { data, errors } = await response.json()
import requests
import json
 
res = requests.delete(
"https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements",
headers={
"Content-Type": "application/vnd.api+json",
"Accept": "application/vnd.api+json",
"Authorization": "Bearer <token>"
},
data=json.dumps({
"data": [
{
"type": "entitlements",
"id": "57f1ceb4-6bf4-44dd-8967-de88364bf9eb"
}
]
})
).json()
import SwiftyJSON
import Alamofire
 
Alamofire.request("https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements",
method: .delete,
headers: [
"Content-Type": "application/vnd.api+json",
"Accept": "application/vnd.api+json",
"Authorization": "Bearer <token>"
],
parameters: [
"data": [
[
"type": "entitlements",
"id": "57f1ceb4-6bf4-44dd-8967-de88364bf9eb"
]
]
],
encoding: JSONEncoding.default
).responseJSON { response in
let json = JSON(data: response.data!)
}
using RestSharp;
 
var client = new RestClient("https://api.keygen.sh/v1/accounts/<account>");
var request = new RestRequest(
"policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements",
Method.DELETE
);
 
request.AddHeader("Content-Type", "application/vnd.api+json");
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <token>");
 
request.AddJsonBody(new {
data = [
new {
type = "entitlements",
id = "57f1ceb4-6bf4-44dd-8967-de88364bf9eb"
}
]
});
 
var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
import org.json.*
 
val body = JSONObject(mapOf(
"data" to listOf(
mapOf(
"type" to "entitlements",
"id" to "57f1ceb4-6bf4-44dd-8967-de88364bf9eb"
)
)
))
 
val res = Unirest.delete("https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/vnd.api+json")
.header("Accept", "application/vnd.api+json")
.body(body)
.asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;
import org.json.*;
 
import static java.util.Map.ofEntries;
import static java.util.Map.entry;
import static java.util.List.of;
 
JSONObject body = new JSONObject(ofEntries(
entry("data", of(
ofEntries(
entry("type", "entitlements"),
entry("id", "57f1ceb4-6bf4-44dd-8967-de88364bf9eb")
)
))
));
 
HttpResponse<JsonNode> res = Unirest.delete("https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/vnd.api+json")
.header("Accept", "application/vnd.api+json")
.body(body)
.asJson();
#include <iostream>
#include <string>
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
 
using namespace std;
using namespace web;
using namespace web::http;
using namespace web::http::client;
using namespace web::json;
using namespace utility;
 
http_client client("https://api.keygen.sh/v1/accounts/<account>");
http_request req;
 
value entl;
entl["type"] = value::string("entitlements");
entl["id"] = value::string("57f1ceb4-6bf4-44dd-8967-de88364bf9eb");
 
value data = value::array(1);
data[0] = entl;
 
value body;
body["data"] = data;
 
req.headers().add("Authorization", "Bearer <token>");
req.headers().add("Content-Type", "application/vnd.api+json");
req.headers().add("Accept", "application/json");
 
req.set_request_uri("/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements");
req.set_method(methods::DELETE);
req.set_body(body.serialize());
 
client.request(req)
.then([](http_response res)
{
auto data = res.extract_json().get();
})
.wait();
curl -X DELETE https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements \
-H 'Content-Type: application/vnd.api+json' \
-H 'Accept: application/vnd.api+json' \
-H 'Authorization: Bearer <token>' \
-d '{
"data": [
{
"type": "entitlements",
"id": "57f1ceb4-6bf4-44dd-8967-de88364bf9eb"
}
]
}'

Example response / 204 No Content

No Content

linkList policy entitlements

Returns a list of entitlements attached to the policy. The entitlements are returned sorted by creation date, with the most recent entitlements appearing first.

linkAuthentication

  • linkBearer

    required

    An authentication token with privileges to view the resource: either an admin, an environment, or the product it belongs to.

linkURL Parameters

  • link<account>

    stringrequired

    The identifier (UUID) or slug of your Keygen account.

  • link<id>

    stringrequired

    The identifier (UUID) of the policy to list entitlements for.

linkQuery Parameters

  • linklimit

    integerdefault=10

    A limit on the number of entitlements to be returned. Limit must be a number between 1 and 100.

    /v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements?limit=25
  • linkpage

    object<string, integer>

    Object containing page size and page number. Page size must be a number between 1 and 100.

    /v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements?page[size]=15&page[number]=2

linkReturns

A 200 OK response will be returned along with a list of entitlement objects.

Upon error, an errors object will be returned along with an HTTP status code indicating the type of error. When an error occurs, the data property will not be included.

Definition

https://api.keygen.sh/v1/accounts/<account>/policies/<id>/entitlements

Example request

const fetch = require("node-fetch")
 
const response = await fetch("https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements?limit=15", {
method: "GET",
headers: {
"Accept": "application/vnd.api+json",
"Authorization": "Bearer <token>"
}
})
 
const { data, errors } = await response.json()
import requests
import json
 
res = requests.get(
"https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements?limit=15",
headers={
"Accept": "application/vnd.api+json",
"Authorization": "Bearer <token>"
}
).json()
import SwiftyJSON
import Alamofire
 
Alamofire.request("https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements?limit=15",
headers: [
"Accept": "application/vnd.api+json",
"Authorization": "Bearer <token>"
]
).responseJSON { response in
let json = JSON(data: response.data!)
}
using RestSharp;
 
var client = new RestClient("https://api.keygen.sh/v1/accounts/<account>");
var request = new RestRequest("entitlements", Method.GET);
 
request.AddHeader("Accept", "application/vnd.api+json");
request.AddHeader("Authorization", "Bearer <token>");
 
request.AddParameter("list", 15);
 
var response = client.Execute(request);
import com.mashape.unirest.http.exceptions.*
import com.mashape.unirest.http.*
 
val res = Unirest.get("https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements")
.header("Authorization", "Bearer <token>")
.header("Accept", "application/vnd.api+json")
.queryString("limit", 15)
.asJson()
import com.mashape.unirest.http.exceptions.*;
import com.mashape.unirest.http.*;
 
HttpResponse<JsonNode> res = Unirest.get("https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements")
.header("Authorization", "Bearer <token>")
.header("Accept", "application/vnd.api+json")
.queryString("limit", 15)
.asJson();
#include <iostream>
#include <string>
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
 
using namespace std;
using namespace web;
using namespace web::http;
using namespace web::http::client;
using namespace utility;
 
http_client client("https://api.keygen.sh/v1/accounts/<account>");
http_request req;
 
req.headers().add("Authorization", "Bearer <token>");
req.headers().add("Accept", "application/json");
 
uri_builder uri("/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements");
uri.append_query("limit", 15);
 
req.set_request_uri(uri.to_uri());
req.set_method(methods::GET);
 
client.request(req)
.then([](http_response res) {
auto data = res.extract_json().get();
})
.wait();
curl https://api.keygen.sh/v1/accounts/<account>/policies/0b4b1a9a-e25a-4f14-a95e-d9dd378d6065/entitlements?limit=15 -g \
-H 'Accept: application/vnd.api+json' \
-H 'Authorization: Bearer <token>'

Example response / 200 OK

{
"data": [
{
"id": "db1ff21b-f42f-4623-952b-ca7f2600bded",
"type": "entitlements",
"attributes": {
"name": "Example Feature",
"code": "EXAMPLE_FEATURE",
"metadata": {},
"created": "2017-01-02T20:26:53.464Z",
"updated": "2017-01-02T20:26:53.464Z"
},
"relationships": {
"account": {
"links": {
"related": "/v1/accounts/<account>"
},
"data": {
"type": "accounts",
"id": "<account>"
}
}
},
"links": {
"self": "/v1/accounts/<account>/entitlements/db1ff21b-f42f-4623-952b-ca7f2600bded"
}
},
]
}