Skip to content

API Keys

Latch uses a two-key model: every “key pair” is one publishable key plus one secret key, sharing the same name.

Each pair contains two keys with different audiences:

  • Publishable key (pk_...) — embedded in browsers. Drives access checks, event ingestion, and customer auth. If it leaks, an attacker can talk to your public API as the same anonymous origin a real visitor would; they cannot mutate subscriptions or read other publications’ data.
  • Secret key (sk_...) — server-side only. Used for subscription mutations and any flow that should not run in a browser. If it leaks, treat it as compromised and rotate immediately.

The two keys are independent records — revoking one does not revoke the other, but the Revoke pair action in the dashboard removes both at once.

Go to Settings > API Keys, give the pair a name (e.g. Production, Staging), and click Create Pair.

You receive both keys exactly once. The dashboard auto-downloads a latch-{name}.env file containing:

LATCH_PUBLISHABLE_KEY=pk_live_xxx
LATCH_SECRET_KEY=sk_live_xxx

You can also use Copy as .env in the banner to copy the same content to your clipboard.

CapabilityPublishable (pk_)Secret (sk_)
Check access (/api/v1/access/check)YesNo
Send events (/api/v1/events)YesNo
Customer auth (register / login / refresh / logout / me)YesYes
Lookup active subscription (/api/v1/subscriptions/me)Yes (via JWT)Yes
Create checkout session (/api/v1/subscriptions/checkout)Yes (via JWT)Yes
Create portal session (/api/v1/subscriptions/portal)Yes (via JWT)Yes
Cancel subscription (/api/v1/subscriptions/cancel)NoYes

“Yes (via JWT)” means the publishable key is accepted, but the customer must additionally be identified through a customer JWT in the Authorization: Bearer ... header — the publishable key alone never grants access to a specific customer’s data.

Access check and event ingestion explicitly reject secret keys to discourage shipping sk_ to browsers. Dashboard-admin CRUD routes use authenticated admin sessions, not API keys.

Run this curl one-liner against your fresh publishable key. A successful call returns a JSON body with a granted boolean.

Terminal window
curl "https://latch-api.v3ck.com/api/v1/access/check?url=https://example.com/" \
-H "X-API-Key: pk_live_..."

If you get 401 Unauthorized, the key is wrong or revoked. If you get 403, double-check the URL belongs to a publication this key has access to.

Use the publishable key in browser code. The SDK reads it once at init and reuses it for all subsequent calls.

<script type="module">
import { init, checkAccess, identify }
from 'https://latch-api.v3ck.com/sdk/latch.js';
// Initialize with your publishable key.
init({
apiKey: 'pk_live_...',
apiUrl: 'https://latch-api.v3ck.com',
});
// Check access on premium pages.
const result = await checkAccess();
if (!result.granted) {
console.log('Paywall:', result.paywallRule);
}
// After your auth flow signs the user in, tell Latch who they are.
identify('reader-id-from-your-auth');
</script>

Use the secret key from your backend. The example below creates a Stripe-backed checkout session.

Terminal window
curl -X POST "https://latch-api.v3ck.com/api/v1/subscriptions/checkout" \
-H "X-API-Key: sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"priceId": "price_abc123",
"customerId": "cus_abc123",
"successUrl": "https://yoursite.com/success",
"cancelUrl": "https://yoursite.com/cancel"
}'

The response contains the url you redirect the customer to.

Revoking a key takes effect immediately and cannot be undone. The dashboard offers two actions:

  • Revoke pair — removes both records in the pair. Use this when retiring an environment.
  • Revoke individual key (the trash icon next to a single pk_/sk_ row) — removes one record only. Useful if a single key leaked but the other side is fine.

After revoke, create a new pair with a different name; do not re-use the old name in scripts that still reference it.