Skip to main content
Unkey Deploy is currently in private beta. To get access, reach out on Discord or email support@unkey.com.
These examples show how to parse the Principal from the X-Unkey-Principal header in common frameworks using API key authentication.
import { Hono } from "hono";

type KeyPrincipal = {
  version: number;
  subject: string;
  type: "key";
  identity?: {
    externalId: string;
    meta: Record<string, string>;
  };
  source: {
    key: {
      keyId: string;
      keySpaceId: string;
      name?: string;
      expiresAt?: number;
      meta: Record<string, string>;
      roles: string[];
      permissions: string[];
    };
  };
};

const app = new Hono();

app.use("*", async (c, next) => {
  const header = c.req.header("x-unkey-principal");
  if (!header) {
    return c.json({ error: "Not authenticated" }, 401);
  }

  const principal: KeyPrincipal = JSON.parse(header);
  c.set("principal", principal);
  await next();
});

app.get("/api/resource", (c) => {
  const principal = c.get("principal") as KeyPrincipal;

  const { permissions } = principal.source.key;
  if (!permissions.includes("api.read")) {
    return c.json({ error: "Insufficient permissions" }, 403);
  }

  const userId = principal.subject;
  const org = principal.identity?.meta?.org;

  return c.json({ userId, org });
});

export default app;
Last modified on March 30, 2026