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.jsonUse 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;
}