For founders

Connect Day Zero to your product

Day Zero is the license server. Your app stores dayzero_ltd_id on the user. We will not tell backers access is ready until a live HTTPS probe succeeds.

What you add

  1. Copy your API key from /dashboard/integration
  2. Set DAYZERO_API_KEY and optionally DAYZERO_ORIGIN
  3. Paste the two routes below
  4. Activate the sandbox LTD, run the sandbox check, then the production probe on a public HTTPS origin
  5. Click Mark access ready — that click re-runs the probe. If it fails, backers stay locked out

app/api/dayzero/activate/route.ts

import { NextResponse, type NextRequest } from "next/server";

export async function GET(request: NextRequest) {
  const code = request.nextUrl.searchParams.get("code");
  const ltdId = request.nextUrl.searchParams.get("ltd_id");
  if (!code) {
    return NextResponse.json({ error: "Missing code" }, { status: 400 });
  }

  const origin = process.env.DAYZERO_ORIGIN ?? "https://dayzero.io";
  const res = await fetch(`${origin}/api/v1/oauth/token`, {
    method: "POST",
    headers: {
      "content-type": "application/json",
      authorization: `Bearer ${process.env.DAYZERO_API_KEY}`,
    },
    body: JSON.stringify({ code }),
  });
  const entitlement = await res.json();
  if (!res.ok || !entitlement.entitled) {
    return NextResponse.json(entitlement, { status: 403 });
  }

  // Persist entitlement.ltd_id on your user (lifetime plan).
  // Then send them into the product.
  const next = new URL("/app", request.url);
  next.searchParams.set("ltd", entitlement.ltd_id ?? ltdId ?? "");
  return NextResponse.redirect(next);
}

app/api/dayzero/probe/route.ts

Return entitled: true only if that LTD is actually granted in your database. Echo the nonce. Day Zero calls this; a dashboard toggle cannot skip it.

import { NextResponse, type NextRequest } from "next/server";

export async function POST(request: NextRequest) {
  const auth = request.headers.get("authorization") ?? "";
  if (auth !== `Bearer ${process.env.DAYZERO_API_KEY}`) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const body = await request.json();
  // Look up body.ltd_id in your users table.
  const entitled = true; // true only if you granted this LTD

  return NextResponse.json({
    nonce: body.nonce,
    ltd_id: body.ltd_id,
    entitled,
  });
}

Secret fallback

const res = await fetch(`${process.env.DAYZERO_ORIGIN}/api/v1/entitlements/verify`, {
  method: "POST",
  headers: {
    "content-type": "application/json",
    authorization: `Bearer ${process.env.DAYZERO_API_KEY}`,
  },
  body: JSON.stringify({ ltd_id, secret }),
});