> ## Documentation Index
> Fetch the complete documentation index at: https://docs.keyport.sbs/llms.txt
> Use this file to discover all available pages before exploring further.

# Version Gating

> Gate license validation by software version to control which versions of your product can run.

Version gating lets you control which versions of your software are permitted to run under a given license. When enabled, the validate endpoint returns version information alongside the standard validation result.

<Tip>
  Want to test version-aware validation live? Use the [Validate API playground](/api-reference/validate) and send a `version` value in the request body.
</Tip>

## Requirements

Version gating is available on paid plans where the product version module is enabled. Enable it for your product in the KeyPort dashboard.

## Sending a version in the validate request

To use version gating, include a `version` field in your `POST /api/v1/validate` request body:

<ParamField body="version" type="string">
  The version of your software making the validation request (e.g. `"2.1.0"`). If omitted, KeyPort falls back to the product's current version.
</ParamField>

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "license_key": "YOUR_LICENSE_KEY",
  "version": "2.1.0"
}
```

## Version response fields

When the version module is enabled, the validate response includes:

<ResponseField name="version" type="string">
  The version that was evaluated. Returns `null` if the version module is disabled.
</ResponseField>

<ResponseField name="version_valid" type="boolean">
  Whether the evaluated version is valid for this license. Returns `null` if the version module is disabled.
</ResponseField>

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "version": "2.1.0",
  "version_valid": true
}
```

## Version gating flow

The product version timeline and license pinning rules work together. Product-level version state decides whether a release is globally allowed, while license-level pinning can narrow that down further for a specific customer.

<div style={{ margin: '1.5rem 0', display: 'grid', gap: '0.85rem' }}>
  <div style={{ border: '1px solid rgba(148,163,184,0.28)', borderRadius: '18px', padding: '1rem 1.1rem', background: 'rgba(37,99,235,0.06)' }}>
    <div style={{ fontSize: '0.8rem', fontWeight: 700, letterSpacing: '0.04em', textTransform: 'uppercase', color: '#1D4ED8', marginBottom: '0.35rem' }}>
      1. App sends version
    </div>

    <div style={{ fontWeight: 600, marginBottom: '0.35rem' }}>
      <code>POST /api/v1/validate</code>
    </div>

    <div style={{ color: 'rgb(71,85,105)' }}>
      Example payload: <code>{`{ "license_key": "YOUR_LICENSE_KEY", "version": "2.2.0" }`}</code>
    </div>
  </div>

  <div style={{ textAlign: 'center', color: 'rgb(100,116,139)', fontWeight: 700 }}>
    Then
  </div>

  <div style={{ border: '1px solid rgba(148,163,184,0.28)', borderRadius: '18px', padding: '1rem 1.1rem', background: 'rgba(16,185,129,0.06)' }}>
    <div style={{ fontSize: '0.8rem', fontWeight: 700, letterSpacing: '0.04em', textTransform: 'uppercase', color: '#047857', marginBottom: '0.5rem' }}>
      2. KeyPort checks product version state
    </div>

    <table>
      <thead>
        <tr>
          <th>Version</th>
          <th>Platform state</th>
          <th>Result</th>
        </tr>
      </thead>

      <tbody>
        <tr>
          <td><code>2.0.x</code></td>
          <td>Allowed</td>
          <td>Can continue</td>
        </tr>

        <tr>
          <td><code>2.1.x</code></td>
          <td>Allowed</td>
          <td>Can continue</td>
        </tr>

        <tr>
          <td><code>2.2.x</code></td>
          <td>Deprecated</td>
          <td>Still valid</td>
        </tr>

        <tr>
          <td><code>2.3.x</code></td>
          <td>Latest</td>
          <td>Valid</td>
        </tr>

        <tr>
          <td><code>2.4.x</code></td>
          <td>Blocked or missing</td>
          <td><code>version\_valid: false</code></td>
        </tr>
      </tbody>
    </table>
  </div>

  <div style={{ textAlign: 'center', color: 'rgb(100,116,139)', fontWeight: 700 }}>
    Then
  </div>

  <div style={{ border: '1px solid rgba(148,163,184,0.28)', borderRadius: '18px', padding: '1rem 1.1rem', background: 'rgba(139,92,246,0.07)' }}>
    <div style={{ fontSize: '0.8rem', fontWeight: 700, letterSpacing: '0.04em', textTransform: 'uppercase', color: '#7C3AED', marginBottom: '0.35rem' }}>
      3. License pinning applies for this customer
    </div>

    <div style={{ marginBottom: '0.4rem' }}>
      Example license rule: <code>>=2.1 \<2.4</code>
    </div>

    <div style={{ color: 'rgb(71,85,105)' }}>
      That means this customer can use <code>2.1.x</code>, <code>2.2.x</code>, and <code>2.3.x</code>, but not <code>2.0.x</code> or anything at <code>2.4.x</code> and above.
    </div>
  </div>

  <div style={{ textAlign: 'center', color: 'rgb(100,116,139)', fontWeight: 700 }}>
    Then
  </div>

  <div style={{ border: '1px solid rgba(148,163,184,0.28)', borderRadius: '18px', padding: '1rem 1.1rem', background: 'rgba(245,158,11,0.08)' }}>
    <div style={{ fontSize: '0.8rem', fontWeight: 700, letterSpacing: '0.04em', textTransform: 'uppercase', color: '#B45309', marginBottom: '0.35rem' }}>
      4. Validate response
    </div>

    <div style={{ color: 'rgb(71,85,105)' }}>
      <code>version\_valid</code> is only <code>true</code> when the version is allowed by the product and also allowed by the license rule for that customer.
    </div>
  </div>
</div>

### How to read this flow

* **Step 1** is the input from your app. Your software sends the version it is currently running.
* **Step 2** is the product-wide rule. KeyPort checks whether that release is allowed, deprecated, latest, blocked, or missing from your configured version list.
* **Step 3** is the customer-specific rule. A license can be pinned to one exact version or to a range such as <code>>=2.1 \<2.4</code>.
* **Step 4** is the final result returned by the API. `version_valid` is only `true` when both the product-level rule and the license-level rule allow the same version.

### What each state means

| State                | Meaning                                                                                                   |
| -------------------- | --------------------------------------------------------------------------------------------------------- |
| `Allowed`            | The version is approved at the product level and can continue to license pinning checks.                  |
| `Deprecated`         | The version is old but still accepted. Validation can still succeed.                                      |
| `Latest`             | The current recommended release for the product.                                                          |
| `Blocked or missing` | The version is not allowed, or it does not exist in the version records. `version_valid` becomes `false`. |

### Simple example

If your product allows `2.0.x` to `2.3.x`, but one customer's license is pinned to <code>>=2.1 \<2.4</code>:

* `2.0.5` fails for that customer even though the product still allows it
* `2.2.0` passes because both checks allow it
* `2.4.0` fails because the product blocks or does not recognize it

## How version validation works

KeyPort determines `version_valid` based on the version record and any pinning rules configured on the license:

* If the version module is **disabled**, both `version` and `version_valid` are `null`.
* If you **don't send a version**, KeyPort falls back to the product's current version.
* If the referenced version record is **missing or blocked**, `version_valid` is `false`.
* **License version pinning** applies on top of the product's version state. Use `version_pin_mode` and `version_range` on a license to allow only exact or ranged versions for that specific customer.

<Info>
  License-level pinning is more restrictive than product-level version state. A version that is valid at the product level can still be rejected if it falls outside a license's pinned range.
</Info>

## When to use version gating

Use version gating when you need to:

* Prevent customers from running deprecated or unsupported versions
* Restrict specific licenses to a particular version or version range
* Roll out new versions gradually by controlling which licenses permit them
