← Heimdall Docs

Quickstart

This guide walks you through a complete Heimdall integration in five steps. By the end, you will have a tenant, a user, a role, and a working token verification flow.

Prerequisites

  • A ProductCraft account with an Admin API key
  • Any HTTP client (curl, fetch, Postman, etc.)

Step 1

Create an App

An App represents a tenant in your system. Every user, role, and permission lives within a specific App. Create one for your first customer or for your own development environment.

curl -X POST https://api.productcraft.co/heimdall/v1/apps \
  -H "Authorization: Bearer YOUR_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "acme-corp",
    "display_name": "Acme Corporation"
  }'

Response:

{
  "id": "app_01HQ3...",
  "name": "acme-corp",
  "display_name": "Acme Corporation",
  "created_at": "2026-02-20T10:00:00Z"
}

Step 2

Define a Role

Roles group permissions together. Create a role for the App and attach the permissions your application needs.

curl -X POST https://api.productcraft.co/heimdall/v1/apps/acme-corp/roles \
  -H "Authorization: Bearer YOUR_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "admin",
    "display_name": "Administrator",
    "permissions": [
      "billing:read",
      "billing:write",
      "users:read",
      "users:write",
      "users:invite"
    ]
  }'

Response:

{
  "id": "role_01HQ3...",
  "app_id": "app_01HQ3...",
  "name": "admin",
  "display_name": "Administrator",
  "permissions": [
    "billing:read",
    "billing:write",
    "users:read",
    "users:write",
    "users:invite"
  ],
  "created_at": "2026-02-20T10:01:00Z"
}

Step 3

Create a User

Add a user to the App and assign them a role. The user is now scoped to this tenant and inherits the permissions of their role.

curl -X POST https://api.productcraft.co/heimdall/v1/apps/acme-corp/users \
  -H "Authorization: Bearer YOUR_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "jane@acme.co",
    "display_name": "Jane Chen",
    "role": "admin"
  }'

Response:

{
  "id": "usr_01HQ3...",
  "app_id": "app_01HQ3...",
  "email": "jane@acme.co",
  "display_name": "Jane Chen",
  "roles": ["admin"],
  "status": "active",
  "created_at": "2026-02-20T10:02:00Z"
}

Step 4

Issue a Token

Authenticate the user (or a service) and receive a signed JWT. The token includes the App context, user ID, and granted permissions.

curl -X POST https://api.productcraft.co/heimdall/v1/apps/acme-corp/tokens \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "password",
    "email": "jane@acme.co",
    "password": "..."
  }'

Response:

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

Step 5

Verify and Authorize

On each incoming request to your API, verify the token and check whether the caller has the required permission. You can do this locally using the JWKS endpoint, or call the authorize endpoint for server-side validation.

curl -X POST https://api.productcraft.co/heimdall/v1/authorize \
  -H "Content-Type: application/json" \
  -d '{
    "token": "eyJhbGciOiJSUzI1NiIs...",
    "permission": "billing:read"
  }'

Response:

{
  "allowed": true,
  "user_id": "usr_01HQ3...",
  "app_id": "app_01HQ3...",
  "permissions": [
    "billing:read",
    "billing:write",
    "users:read",
    "users:write",
    "users:invite"
  ]
}

Local token verification (optional)

For lower latency, you can 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://api.productcraft.co/heimdall/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. The token payload includes app_id, user_id, roles, and permissions claims.