Auth docs
Quickstart

Quickstart.

Auth in five steps.

By the end of this guide you’ll have an account, an App, roles, and a working token verification flow. Plan ten minutes.


Prerequisites

  • Any HTTP client (curl, fetch, Postman, etc.)

Step 1

Create an account

Sign up for a Auth account. This gives you an identity that can create and manage Apps.

POST /api/v1/auth/signup
curl -X POST https://api.auth.productcraft.co/v1/auth/signup \
  -H "Content-Type: application/json" \
  -d '{
    "email": "you@example.com",
    "username": "yourname",
    "password": "YourSecurePassword123"
  }'

Response

{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "refresh_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 3600
}

Save the access_token — you'll use it in the next steps.


Step 2

Create an App

An App represents a tenant in your system. Every role, permission, and invite lives within a specific App. Create one for your first customer or your development environment — you become the owner automatically.

POST /api/v1/apps
curl -X POST https://api.auth.productcraft.co/v1/apps \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "slug": "acme-corp",
    "displayName": "Acme Corporation"
  }'

Response

{
  "id": "550e8400-e29b-41d4-a716-...",
  "slug": "acme-corp",
  "display_name": "Acme Corporation",
  "status": "active",
  "metadata": {},
  "created_at": "2026-02-20T10:00:00Z"
}

Three system roles are created automatically: owner, admin, and member.


Step 3

Invite an end-user

Pre-allocate an EndUser of your App by minting an invite. Auth emails the invitation via your workspace's verified Mail sender; the recipient sets their password by POSTing the code back to the Consumer API.

POST /api/v1/apps/acme-corp/end-users/invites
curl -X POST https://api.auth.productcraft.co/v1/apps/acme-corp/end-users/invites \
  -H "Authorization: Bearer YOUR_WORKSPACE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "newuser@example.com",
    "name": "New User",
    "roleName": "member",
    "expiresInHours": 72
  }'

The recipient receives an email containing the invite code. They accept by POSTing the code to your App's accept endpoint:

POST /:appSlug/v1/auth/accept-invite
curl -X POST https://api.auth.productcraft.co/acme-corp/v1/auth/accept-invite \
  -H "Content-Type: application/json" \
  -d '{ "code": "inv_…", "password": "CorrectHorseBatteryStaple" }'

On success the response is the same shape as a sign-in: an access + refresh token pair scoped to the App. Workspace teammates managing the App itself (not end-users) are workspace members — invite them at auth.productcraft.co/workspaces instead.


Step 4

Check permissions

Use the introspection endpoint to see what permissions a user has within a specific App.

GET /api/v1/introspect/apps/:slug
curl https://api.auth.productcraft.co/v1/introspect/apps/acme-corp \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Response

{
  "isMember": true,
  "role": { "id": "...", "name": "owner" },
  "permissions": [
    "user.create",
    "user.read",
    "user.update",
    "user.delete",
    "user.list",
    "role.create",
    "role.read",
    "..."
  ]
}

Step 5

Verify tokens locally

For production use, verify tokens locally using the public JWKS endpoint. Fetch the keys once, cache them, and verify tokens without a network round-trip on every request.

JWKS endpoint
GET https://api.auth.productcraft.co/<appSlug>/v1/.well-known/jwks.json

Each app has its own signing key. Pin the JWKS URL and the issuer to YOUR app — a token minted for another app on the platform cannot pass.

Use any JWT library in your language of choice (jose, jsonwebtoken, PyJWT, etc.) to verify the token signature against these keys.

verify.ts
import * as jose from 'jose';

const APP_SLUG = 'acme';

const JWKS = jose.createRemoteJWKSet(
  new URL(`https://api.auth.productcraft.co/${APP_SLUG}/v1/.well-known/jwks.json`)
);

async function verifyToken(token) {
  const { payload } = await jose.jwtVerify(token, JWKS, {
    issuer:   `https://api.auth.productcraft.co/${APP_SLUG}`,
    audience: APP_SLUG,
  });
  return payload;
}