← Heimdall Docs

Quickstart

This guide walks you through a complete Heimdall integration in five steps. By the end, you will have an account, an App, roles, and a working token verification flow.

Prerequisites

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

Step 1

Create an account

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

curl -X POST https://heimdall.productcraft.co/api/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 will 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 for your development environment. You become the owner automatically.

curl -X POST https://heimdall.productcraft.co/api/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 a team member

Create an invite to bring another user into your App with a specific role. First, list your App's roles to find the role name you want to assign.

# List roles to find the admin role name
curl https://heimdall.productcraft.co/api/v1/apps/acme-corp/roles \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

# Create an invite
curl -X POST https://heimdall.productcraft.co/api/v1/apps/acme-corp/invites \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "role": "admin",
    "email": "colleague@example.com",
    "maxUses": 1,
    "expiresInHours": 72
  }'

The response includes a code field. Send this code to your colleague. They sign up, then accept the invite:

curl -X POST https://heimdall.productcraft.co/api/v1/invites/accept \
  -H "Authorization: Bearer COLLEAGUE_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "code": "INVITE_CODE" }'

Step 4

Check permissions

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

curl https://heimdall.productcraft.co/api/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.

GET https://heimdall.productcraft.co/api/v1/.well-known/jwks.json

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

import * as jose from 'jose';

const JWKS = jose.createRemoteJWKSet(
  new URL('https://heimdall.productcraft.co/api/v1/.well-known/jwks.json')
);

async function verifyToken(token) {
  const { payload } = await jose.jwtVerify(token, JWKS, {
    issuer: 'https://heimdall.productcraft.co/api',
  });
  return payload;
}