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

# Avalex License Validation: How It Works and What It Checks

> Understand how Avalex validates software licenses: product binding, expiration, IP slot allocation, HWID slot allocation, and concurrency safety.

When your application calls `POST /licenses/validate`, Avalex runs a fast, sequential series of checks against the license record stored in the database. Each check must pass before the next one runs. If any check fails, Avalex immediately returns `{"valid": false}` and records the failed attempt in the validation history — no partial grants are ever issued.

## Validation Checks

The four checks run in the following order:

| Check                | Criteria                                                                                                                                           | On Failure     |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- |
| **Product ID Match** | The `productId` in the request must exactly match the `productId` recorded on the license                                                          | `valid: false` |
| **Expiration**       | The current server time must be earlier than the license's `expiresAtEpochMillis` (only evaluated if `expiresAtEpochMillis` is set on the license) | `valid: false` |
| **IP Slot**          | The client's IP address is already bound to this license, OR the number of currently bound IPs is below `maxIps`                                   | `valid: false` |
| **HWID Slot**        | The `hwid` in the request is already bound to this license, OR the number of currently bound HWIDs is below `maxHwids`                             | `valid: false` |

### Notes on Slot Behaviour

* If `maxIps` or `maxHwids` is `null`, there is **no limit** on that dimension — Avalex registers new IPs or HWIDs freely without rejecting the request.
* A client IP or HWID that was bound during a previous successful validation does **not** consume an extra slot on subsequent calls. Avalex recognises the existing binding and counts it as the same slot.
* Every validation attempt — whether it returns `valid: true` or `valid: false` — is written to the license's validation history. You can review the full history in the Admin Portal to investigate unusual activity.

## Concurrency Safety

Avalex handles simultaneous validation requests for the same license automatically. If two requests arrive at the same time and both need to register a new IP or HWID binding, Avalex resolves the conflict internally with built-in retry logic — no coordination is required on your end. From your application's perspective, concurrent validations are safe and you do not need to implement any locking or serialisation on the client side.

## Rate Limiting

The public validation endpoint enforces a limit of **30 requests per minute per IP address**. If your application exceeds this, the endpoint responds with HTTP 429:

```json theme={null}
{ "error": "Too many validation attempts. Try again shortly." }
```

Design your integration so that your application validates on startup and then at a periodic interval, rather than on every user action or API call.

<Tip>
  Validate the license when your application launches and then once every **6–24 hours** in the background. Avoid calling the validation endpoint on every user interaction — it is unnecessary for enforcement, burns through your rate-limit budget, and adds latency to your UI. Pair periodic validation with a local cache and a grace period so users are not disrupted by brief network outages.
</Tip>
