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

# Is this licence key still valid

> Authenticated with your API key and scoped to your account · you can only ask about licences you issued, which is what keeps this from being an enumeration oracle. Your customer's software cannot call it directly (that would ship `sk_live` inside it) · your backend relays the check.

`instanceId` is optional · with it, `instance` describes that machine's seat. An unknown instance is not an error, it comes back `null`.

An expired or revoked licence answers `200` with its `status` · only a key that is not on your account is a `404`. Cache for a few minutes rather than calling on every request.



## OpenAPI

````yaml /v3-beta/api-reference/openapi.yaml post /v3/licenses/validate
openapi: 3.1.0
info:
  title: Suby.fi Merchant API
  version: 3.0.0-beta
  description: >
    The **v3** public merchant API for Suby.fi. RESTful (plural,
    resource-oriented

    endpoints under the `/v3` prefix). Authenticate every request

    with your secret API key in the `X-Suby-Api-Key` header.


    - `sk_live_…` keys operate in **production** (real funds).

    - `sk_sandbox_…` keys operate in a fully simulated **sandbox** (test cards,
      Base Sepolia crypto, no real money). The environment is derived from the
      key prefix.
  contact:
    email: contact@suby.fi
    url: https://suby.fi
servers:
  - url: https://api.beta.suby.fi
    description: Production + sandbox (environment selected by API key prefix)
security:
  - ApiKeyAuth: []
tags:
  - name: Products
    description: Manage your product catalog (one-time and recurring).
  - name: Checkout
    description: >-
      Hosted checkout · signed session tokens (`cs_…`). Every card Suby holds
      was collected here, which is what keeps card data out of your systems.
  - name: Payments
    description: >-
      Read payments and receipts, refund them, and debit a stored instrument
      off-session (pay-as-you-go). Collecting a card happens on the hosted
      checkout, never here.
  - name: Subscriptions
    description: >-
      Drive a live subscription · read it, change its plan, end it.
      Subscriptions are opened by a checkout session, not by this API.
  - name: Discount Codes
    description: Promo codes, redeemed at checkout.
  - name: Crypto
    description: >-
      The headless rail · quote, charge, and settle on-chain from inside your
      own site. No card data is involved, so none of the constraints that keep
      card collection on a Suby page apply here.
  - name: Customers
    description: First-class customer records with billing address.
  - name: Payment Methods
    description: >-
      Read and detach the cards a customer has stored. They are created by a
      checkout session (`savePaymentMethod`, or `mode=setup`) · the only place a
      card is collected.
  - name: Licence Key
    description: >-
      The licence server · validate a key, take a seat, free one. Authenticated
      with your API key like everything else, and scoped to the licences you
      issued, so your backend relays the check rather than your customer's
      software calling it directly.
paths:
  /v3/licenses/validate:
    post:
      tags:
        - Licence Key
      summary: Is this licence key still valid
      description: >-
        Authenticated with your API key and scoped to your account · you can
        only ask about licences you issued, which is what keeps this from being
        an enumeration oracle. Your customer's software cannot call it directly
        (that would ship `sk_live` inside it) · your backend relays the check.


        `instanceId` is optional · with it, `instance` describes that machine's
        seat. An unknown instance is not an error, it comes back `null`.


        An expired or revoked licence answers `200` with its `status` · only a
        key that is not on your account is a `404`. Cache for a few minutes
        rather than calling on every request.
      operationId: validateLicense
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - key
              properties:
                key:
                  type: string
                  example: A7K2-M4P9-QW3E-R8TY
                instanceId:
                  type: string
                  description: From `activate` · reads that machine's seat.
      responses:
        '200':
          description: The licence
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/License'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: LICENSE_NOT_FOUND · no such licence on your account
        '429':
          description: RATE_LIMITED
components:
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      description: >-
        Optional key (≤255 chars, e.g. a UUID v4) making this POST safe to retry
        · the response is cached 24h and a retry with the SAME key replays it
        instead of re-executing. The same key with a different body → `422
        IDEMPOTENCY_KEY_CONFLICT`; a retry while the first is in flight → `409`.
      schema:
        type: string
        maxLength: 255
        example: 5f3b9c2e-1a4d-4f2b-9c31-7e2a1b6d8c04
  schemas:
    License:
      allOf:
        - $ref: '#/components/schemas/SuccessEnvelope'
        - type: object
          properties:
            data:
              type: object
              properties:
                id:
                  type: string
                  example: lic_abc123
                productId:
                  type: string
                  nullable: true
                  description: >-
                    The product this licence was sold with, when the sale
                    carried one.
                customerId:
                  type: string
                  example: cus_abc123
                status:
                  type: string
                  enum:
                    - active
                    - inactive
                    - expired
                    - disabled
                  description: >-
                    `active` · good to run. `inactive` · issued but never
                    claimed by the buyer. `expired` · past its expiry, or the
                    grant behind it lapsed. `disabled` · revoked: refunded,
                    charged back, or cut off by you.
                keyLast4:
                  type: string
                  description: >-
                    Last four characters of the key. The key itself is never
                    echoed · you already hold it, and a secret in a response
                    body is a secret in every log.
                activation:
                  type: integer
                  description: Seats currently taken.
                activationLimit:
                  type: integer
                  nullable: true
                  description: Seat cap, or null for unlimited.
                expiresAt:
                  type: string
                  format: date-time
                  nullable: true
                createdAt:
                  type: string
                  format: date-time
                sandbox:
                  type: boolean
                instance:
                  nullable: true
                  description: >-
                    The instance this call concerned · the one activated, the
                    one deactivated, or the one named on a validate. Null when
                    the call named none.
                  type: object
                  properties:
                    id:
                      type: string
                      description: Minted by Suby at activation. Store it; send it back.
                    name:
                      type: string
                      nullable: true
                    status:
                      type: string
                      enum:
                        - active
                        - deactivated
                    createdAt:
                      type: string
                      format: date-time
    SuccessEnvelope:
      type: object
      required:
        - success
        - data
      properties:
        success:
          type: boolean
          example: true
        message:
          type: string
        data:
          description: Endpoint-specific payload.
    Error:
      type: object
      required:
        - success
        - error
      properties:
        success:
          type: boolean
          example: false
        error:
          type: string
          description: Machine-readable error code.
          example: NOT_FOUND
        message:
          type: string
          example: Resource not found
        data:
          description: Optional error detail.
  responses:
    Unauthorized:
      description: Invalid or missing API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            success: false
            error: UNAUTHORIZED
            message: Invalid or missing API key
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-Suby-Api-Key
      description: Secret API key. `sk_live_…` (production) or `sk_sandbox_…` (sandbox).

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.