Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Getting Started with Alloy

Go from zero to managing tickets in 5 minutes — using nothing but curl.

Prerequisites

  • Rust toolchain (1.75+): Install via rustup if you don’t have it
  • Git: To clone the repository
  • curl and jq: For interacting with the API

Or use a prebuilt binary from the Releases page — no Rust toolchain needed.

Step 1: Start the Server

Alloy runs in SQLite mode by default — no database setup, no Docker, no config files. JWT signing keys are auto-generated if not configured.

# Clone and enter the repo
git clone https://github.com/your-org/alloy.git
cd alloy

# Build the release binary
cargo build --release

# Start the server with open registration enabled
ALLOY_REGISTRATION=open ./target/release/alloy serve

Expected output:

WARN: No JWT keys configured — auto-generating Ed25519 key pair for development.
       Set ALLOY_JWT_PRIVATE_KEY / ALLOY_JWT_PUBLIC_KEY for production.
Running migrations...
Migrations complete.
Listening on 0.0.0.0:3000

Note: The auto-generated keys are ephemeral — they change on every restart, which invalidates existing tokens. For production, set ALLOY_JWT_PRIVATE_KEY_FILE and ALLOY_JWT_PUBLIC_KEY_FILE pointing to Ed25519 PEM files. See the Deployment Guide for details.

Leave this terminal running and open a new one for the remaining steps. Set the base URL variable:

BASE_URL="http://localhost:3000"

Step 2: Register a User

Create your first user account via the registration endpoint:

curl -s -X POST "$BASE_URL/api/v1/auth/register" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "tutorial@alloy.dev",
    "password": "tutorial1",
    "display_name": "Tutorial User"
  }' | jq .
{
  "user_id": "a1b2c3d4-...",
  "email": "tutorial@alloy.dev",
  "display_name": "Tutorial User",
  "access_token": "eyJ..."
}

Save the token and user ID for subsequent requests:

TOKEN="<access_token from above>"
USER_ID="<user_id from above>"

CLI equivalent:

cargo run -p alloy-cli -- auth login --email tutorial@alloy.dev --password tutorial1

Step 3: Create an Organization

curl -s -X POST "$BASE_URL/api/v1/orgs" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "name": "Tutorial Corp",
    "slug": "tutorial-corp"
  }' | jq .
{
  "id": "b2c3d4e5-...",
  "name": "Tutorial Corp",
  "slug": "tutorial-corp"
}

Save the org ID:

ORG_ID="<id from above>"

Verify it was created:

curl -s "$BASE_URL/api/v1/orgs" \
  -H "Authorization: Bearer $TOKEN" | jq .
{
  "items": [
    {
      "id": "b2c3d4e5-...",
      "name": "...",
      "slug": "..."
    }
  ]
}

CLI equivalent:

cargo run -p alloy-cli -- onboard --email tutorial@alloy.dev --password tutorial1 --org-name "Tutorial Corp" --org-slug tutorial-corp

Roles and Permissions

When you created the organization above, Alloy automatically assigned you the Owner role — the most privileged role available. Every organization member has exactly one of five roles:

RoleDescription
OwnerFull control. Assigned automatically to the org creator.
AdminManage workflows, teams, invites, and delete resources.
MemberCreate and update projects, tickets, sprints, and time entries.
ReporterCreate tickets and comments. Limited to assigned projects.
ViewerRead-only access to all resources.

Inviting a Team Member

As an Owner, you can invite others to join your organization. Each invite specifies the role the new member will receive:

curl -s -X POST "$BASE_URL/api/v1/orgs/$ORG_ID/invites" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d "{
    \"email\": \"teammate@example.com\",
    \"role\": \"member\",
    \"created_by\": \"$USER_ID\"
  }" | jq .
{
  "id": "...",
  "invite_code": "...",
  "invite_link": "...",
  "email": "teammate@example.com",
  "role": "Member",
  "expires_at": "..."
}

Share the invite_link with your teammate. They can register using the invite code to join with the specified role.

For the full permission matrix showing which role is required for each operation, see the Roles and Permissions section of the API Reference.

Step 4: Create a Project

curl -s -X POST "$BASE_URL/api/v1/projects" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d "{
    \"org_id\": \"$ORG_ID\",
    \"key\": \"DEMO\",
    \"name\": \"Demo Project\",
    \"description\": \"A demo project for Alloy\"
  }" | jq .
{
  "id": "c3d4e5f6-...",
  "org_id": "b2c3d4e5-...",
  "key": "DEMO",
  "name": "Demo Project",
  "description": "A demo project for Alloy"
}

Save the project ID:

PROJECT_ID="<id from above>"

Read it back to confirm:

curl -s "$BASE_URL/api/v1/projects/$PROJECT_ID" \
  -H "Authorization: Bearer $TOKEN" | jq .
{
  "id": "c3d4e5f6-...",
  "key": "DEMO",
  "name": "Demo Project",
  "description": "A demo project for Alloy"
}

CLI equivalent:

cargo run -p alloy-cli -- project create --org-id "$ORG_ID" --key DEMO --name "Demo Project"

Step 5: Create Your First Ticket

curl -s -X POST "$BASE_URL/api/v1/projects/$PROJECT_ID/tickets" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d "{
    \"title\": \"Set up CI pipeline\",
    \"description\": \"Configure GitHub Actions for build and test\",
    \"status\": \"Backlog\",
    \"priority\": \"High\",
    \"reporter_id\": \"$USER_ID\"
  }" | jq .
{
  "id": "d4e5f6g7-...",
  "title": "Set up CI pipeline",
  "description": "Configure GitHub Actions for build and test",
  "status": "Backlog",
  "priority": "High",
  "reporter_id": "a1b2c3d4-..."
}

Save the ticket ID:

TICKET_ID="<id from above>"

CLI equivalent:

cargo run -p alloy-cli -- ticket create --title "Set up CI pipeline" --priority high

Step 6: Add a Comment

curl -s -X POST "$BASE_URL/api/v1/tickets/$TICKET_ID/comments" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d "{
    \"body\": \"Looks good, let's ship it\",
    \"author_id\": \"$USER_ID\"
  }" | jq .
{
  "id": "e5f6g7h8-...",
  "body": "Looks good, let's ship it",
  "author_id": "a1b2c3d4-...",
  "ticket_id": "d4e5f6g7-..."
}

CLI equivalent:

cargo run -p alloy-cli -- comment create --ticket-id "$TICKET_ID" --body "Looks good, let's ship it"

Step 7: List Tickets

Verify everything by listing tickets in the project:

curl -s "$BASE_URL/api/v1/projects/$PROJECT_ID/tickets" \
  -H "Authorization: Bearer $TOKEN" | jq .
{
  "items": [
    {
      "id": "d4e5f6g7-...",
      "title": "Set up CI pipeline",
      "status": "Backlog",
      "priority": "High"
    }
  ]
}

CLI equivalent:

cargo run -p alloy-cli -- ticket list

You’re up and running!

Seed a Full Demo

Want a richer dataset to explore? The included seed script creates an org, user, project, labels, a sprint, six tickets, comments, and time entries — all with read-back validation:

BASE_URL=http://localhost:3000 bash scripts/seed-demo.sh

Learn More

References

  • API Reference — Full endpoint documentation, field tables, and permission matrix
  • CLI Reference — Complete list of commands and options for the Alloy CLI
  • TUI Guide — Interactive terminal UI for browsing and managing work
  • MCP Guide — Use Alloy through the Model Context Protocol with AI assistants
  • MCP Tools Reference — Detailed reference for all MCP tool parameters and behavior
  • Deployment — Production deployment with PostgreSQL, Docker, TLS, and multi-tenancy

Guides

Use Cases

Playbooks

Tutorials