Runtime Data API

Authenticate your app's end users and make authenticated record API calls against your Knack application from a custom frontend.

Overview

The Knack Runtime Data API lets your custom frontend authenticate end users and perform create, read, update, and delete operations on Knack data on their behalf. When a user logs in through your frontend, Knack issues a short-lived Bearer token (lao_ prefix) that your app attaches to every subsequent API request.

This is the primary API for developers building custom frontends — React apps, mobile apps, third-party tools, or AI-generated UIs — that use Knack as their backend database. All data lives in Knack; your frontend is simply the interface.

Note: This guide covers runtime record access from custom frontends. For building the underlying data model (tables, fields, relationships), see the Knack MCP Server guide.

How it works

Each API request is scoped to an authenticated user, which means:

  • Data access is enforced per user — if your Knack app has Data Access Control (DAC) enabled, each user only sees the records they're permitted to access.
  • System fields are populated automaticallyCreated By, Updated By, and Owned By reflect the identity of the user making the request, giving you accurate ownership and audit trails.
  • Tokens are app-scoped — a token issued for one Knack application cannot be used against a different application.

Token types

TokenPrefixLifetimePurpose
Access tokenlao_1 hourAuthenticates runtime API calls
Refresh tokenlrt_30 daysObtains a new access token without re-login

Table of Contents

  1. Overview
  2. Step 1 — Register an OAuth Client
  3. Step 2 — Authorization Flow (PKCE)
  4. Step 3 — Exchange Code for Tokens
  5. Step 4 — Make Authenticated Record API Calls
  6. Step 5 — Refresh the Access Token
  7. Step 6 — Revoke Tokens
  8. Error Responses
  9. Notes for Implementation

Base URL

https://<your-knack-api-domain>

Step 1 — Register an OAuth Client

Before your frontend can authenticate users, register it as an OAuth client. Registration is idempotent — the same client_name + redirect_uris + application_id always returns the same client_id, so it's safe to call this at app startup or build time.

POST /v1/oauth/register
Content-Type: application/json

{
  "client_name": "My Custom Frontend",
  "redirect_uris": ["https://myapp.example.com/callback"],
  "application_id": "<knack_app_id>"
}

Response 201 (new) or 200 (existing):

{
  "client_id": "<client_id>",
  "redirect_uris": ["https://myapp.example.com/callback"],
  "client_name": "My Custom Frontend",
  "application_id": "<knack_app_id>"
}

Fields:

FieldTypeNotes
client_namestringRequired. Displayed on the login screen your users see.
redirect_urisstring[]Required. Must use https.
application_idstringRequired. The 24-char hex ID of your Knack application.

Step 2 — Authorization Flow (PKCE)

Your frontend initiates a PKCE-based OAuth flow to authenticate each user. PKCE (Proof Key for Code Exchange) ensures the flow is secure even in environments where a client secret cannot be stored safely, such as browser apps or mobile clients.

2a. Generate PKCE parameters

Generate a fresh code_verifier and code_challenge for every authorization attempt — these are single-use.

const crypto = require('crypto');

const codeVerifier = crypto.randomBytes(48).toString('base64url');
const codeChallenge = crypto.createHash('sha256')
  .update(codeVerifier)
  .digest('base64url');

const state = crypto.randomBytes(16).toString('hex');

2b. Redirect the user to the authorization endpoint

Send the user to Knack's authorization endpoint. Knack renders a login form where your user enters their credentials.

GET /v1/oauth/authorize
  ?client_id=<client_id>
  &redirect_uri=<redirect_uri>
  &response_type=code
  &code_challenge=<code_challenge>
  &code_challenge_method=S256
  &state=<state>

Required parameters:

ParameterValue
client_idFrom Step 1
redirect_uriMust exactly match a registered URI
response_typecode
code_challengebase64url(sha256(code_verifier))
code_challenge_methodS256
stateRandom hex string for CSRF protection

2c. User logs in and is redirected back

After the user authenticates successfully, Knack redirects back to your redirect_uri with a short-lived authorization code:

<redirect_uri>?code=<auth_code>&state=<state>

Always validate state before proceeding — reject mismatches to prevent CSRF attacks. The authorization code is valid for 5 minutes and is single-use.


Step 3 — Exchange Code for Tokens

Exchange the authorization code for an access token and refresh token. Your frontend attaches the access token to every runtime API call made on behalf of the user.

POST /v1/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=<auth_code>
&redirect_uri=<redirect_uri>
&client_id=<client_id>
&code_verifier=<code_verifier>

Response 200:

{
  "access_token": "lao_<hex>",
  "refresh_token": "lrt_<hex>",
  "token_type": "Bearer",
  "expires_in": 3599
}

Store these tokens securely — see the Notes for Implementation section for guidance.


Step 4 — Make Authenticated Record API Calls

Attach the access token to every request your frontend makes to the Runtime Data API. Knack uses the token to identify the user, enforce data access rules, and populate system fields.

GET /v1/objects/<object_key>/records
X-Knack-Application-Id: <knack_app_id>
Authorization: Bearer lao_<access_token>

Supported endpoints

MethodPathDescription
GET/v1/objects/<key>/recordsList records
GET/v1/objects/<key>/records/<id>Get record
POST/v1/objects/<key>/recordsCreate record
PUT/v1/objects/<key>/records/<id>Update record
DELETE/v1/objects/<key>/records/<id>Delete record

Data access and ownership

  • Data Access Control (DAC): If settings.accessControlEnforced: true is set on your app, records are automatically filtered to what the authenticated user is permitted to see. Your frontend does not need to implement this logic — Knack handles it server-side at runtime.
  • System fields: Created By, Updated By, and Owned By are automatically populated with the authenticated user's identity on every write operation.

Step 5 — Refresh the Access Token

Access tokens expire after 1 hour. Use the refresh token to obtain a new access token without requiring the user to log in again. Each refresh rotates both tokens — the old refresh token is immediately invalidated.

POST /v1/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token=lrt_<refresh_token>
&client_id=<client_id>

Step 6 — Revoke Tokens

When a user logs out of your frontend, revoke their tokens to invalidate the session on Knack's side. Revoking either token type invalidates all tokens (access + refresh) for that user and client pair.

POST /v1/oauth/revoke
Content-Type: application/x-www-form-urlencoded

token=lao_<access_token>&client_id=<client_id>

Error Responses

HTTPerrorCause
400invalid_requestMissing or malformed parameter
400invalid_grantCode expired, already used, or PKCE mismatch
400invalid_clientUnknown client_id or application not found
401invalid_tokenAccess token missing, expired, or invalid
403login_disactivatedUser account is inactive
403login_pending_approvalUser account is pending approval
429Too many failed login attempts

Notes for Implementation

  • Client registration is one-time: store client_id after the first call; re-registering returns the same ID.
  • PKCE is required: generate a fresh code_verifier and code_challenge for every authorization attempt. Never reuse them.
  • Session cookies are required for the authorize/login flow. A browser handles this automatically; ensure your frontend does not strip cookies during the redirect.
  • state must be validated: compare it to what was sent before exchanging the code. Reject mismatches.
  • Token storage: store tokens in httpOnly cookies or a secure server-side session. Avoid localStorage — it is accessible to JavaScript and vulnerable to XSS.
  • Proactive token refresh: refresh the access token a few minutes before it expires (e.g., at 55 minutes) rather than waiting for a 401. This avoids interrupting your user's session.
  • Content-Type: application/x-www-form-urlencoded is required for the token and revoke endpoints — not application/json.