> ## 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.

# Quick Start

> Get your first live license validation working in about five minutes.

Follow these steps to go from a new account to a working license validation call.

<Tip>
  After you finish the setup steps below, you can try the real request directly from the [Validate API playground](/api-reference/validate).
</Tip>

<Steps>
  <Step title="Create an account">
    Open [app.keyport.sbs](https://app.keyport.sbs) and sign in with email, password, or Discord.
  </Step>

  <Step title="Create an organization">
    Create an organization with a name and slug. Both Free and Pro plans allow up to 2 organizations per user.
  </Step>

  <Step title="Create a product">
    Create a product inside your organization. KeyPort shows you the product API key once at creation time:

    ```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
    kp_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    ```

    Store the full key securely. Only the prefix is shown again later.
  </Step>

  <Step title="Create a license">
    Create a license for the product and attach at least one customer identifier — a customer email or Discord ID. Set a lifetime or expiry date, and set `max_ips` if you want per-license IP restrictions.
  </Step>

  <Step title="Validate from your app">
    Send the license key to the public API using your product API key as the bearer token:

    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    curl -X POST https://api.keyport.sbs/api/v1/validate \
      -H "Authorization: Bearer kp_live_xxxxxxxxxxxxxxxxxxxxxxxxx" \
      -H "Content-Type: application/json" \
      -d '{"license_key":"ABCD-EFGH-IJKL-MNOP"}'
    ```

    A successful response looks like this:

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "valid": true,
      "status": "active",
      "expires": null,
      "ip_registered": true,
      "ip_count": 1,
      "max_ips": 1,
      "version": null,
      "version_valid": null,
      "custom": null,
      "signature": null
    }
    ```
  </Step>

  <Step title="Enforce the result in your app">
    Gate access based on the response. Allow access only when `valid === true`.

    Handle the `status` field to surface the right message to your users:

    * `expired` — the license has passed its expiry date
    * `revoked` — the license was manually revoked
    * `ip_blocked` — this IP is explicitly blocked for the license
    * `ip_limit_reached` — the license has hit its `max_ips` limit
    * `ip_not_registered` — the calling IP has not been registered for this license

    Handle API-level errors separately:

    * `401 invalid_api_key` — your product API key is wrong or missing (configuration issue on your side)
    * `429 rate_limit_exceeded` — you have hit a temporary upstream limit
  </Step>
</Steps>

<Note>
  The `status` field always tells you the specific reason a license is not usable. Checking only `valid` is enough to gate access, but reading `status` lets you show accurate, actionable error messages to your customers.
</Note>
