Valqio Docs

Quickstart

Make one access check, one runtime decision, and inspect the evidence they create.

This path proves the Valqio integration loop with one product action. The example action is generation-runs, but the same shape works for API calls, exports, reports, seats, storage, model tokens, or any other costly product work.

1. Install the SDK

npm install @valqio/sdk-node

2. Configure runtime environment values

Use hosted values from the Valqio Console for your project and environment.

VALQIO_API_KEY=<server runtime key>
VALQIO_DATA_PLANE_URL=<hosted runtime API URL>
VALQIO_PROJECT_ID=<project id>
VALQIO_ENVIRONMENT=<environment key>

Do not print API keys or paste them into logs, screenshots, or support tickets.

3. Create a runtime client

import { createRuntimeClient } from '@valqio/sdk-node'

const runtime = createRuntimeClient({
  apiKey: process.env.VALQIO_API_KEY!,
  baseUrl: process.env.VALQIO_DATA_PLANE_URL!,
  projectId: process.env.VALQIO_PROJECT_ID!,
  environment: process.env.VALQIO_ENVIRONMENT!,
  mode: 'remote-only',
})

4. Call Valqio before the billable action

This is the access-then-consume path: check feature access without consuming usage, then enforce usage before the costly work starts.

export async function generateReport(requestId: string, workspaceId: string) {
  const idempotencyKey = `generate-report:${requestId}`
  const subject = {
    type: 'customer' as const,
    key: workspaceId,
  }

  const access = await runtime.evaluate({
    requestId,
    subject,
    checks: [{ key: 'report-export', type: 'flag' }],
  })

  const reportExport = access.results.find((result) => result.key === 'report-export')

  if (reportExport?.decision !== 'allow') {
    return {
      status: 403,
      body: {
        reason: 'upgrade_required',
        reasonCode: reportExport?.reasonCode,
        requestId,
      },
    }
  }

  const decision = await runtime.enforce({
    requestId,
    meterKey: 'generation-runs',
    quantity: 1,
    subject,
    idempotencyKey,
  })

  if (!decision.allowed) {
    return {
      status: 402,
      body: {
        reasonCode: decision.reasonCode,
        requestId,
        idempotencyKey,
      },
    }
  }

  const result = await runExpensiveGeneration()

  return {
    status: 200,
    body: {
      result,
      requestId,
      idempotencyKey,
    },
  }
}

For generated helper examples, see feature and parameter access.

5. Inspect the evidence

After the request, open Console and inspect the decision record. The evidence should explain:

  • which subject asked to run work
  • which meter or action was evaluated
  • whether the decision was allowed or denied
  • what remaining balance, quota, or limit context was used
  • which idempotency key protected retries
  • which request ID ties the Console record back to your app logs

That evidence is the handoff from runtime enforcement to support, finance, customer success, analytics, and billing sync.

On this page