Forgecroft Docs
Quickstart

API-First Quickstart

Set up Forgecroft entirely from the command line — no console needed. This is the starting point for CI/CD integrations, scripts, and automation.

This guide walks you through the Forgecroft API using curl. By the end you’ll have triggered a plan and streamed its logs. Everything here also works with the Go SDK and CLI.

Prerequisites

Set your API key:

export FC_API=https://api.forgecroft.com
export FC_KEY=fc_live_...

The POST /onboard endpoint creates everything in a single request — project, credentials, state backend, and workspace:

curl -s -X POST \
  -H "Authorization: Bearer $FC_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "managed",
    "project_name": "Infrastructure",
    "credential": {
      "name": "AWS Production",
      "credential_type": "aws_static",
      "secrets": {
        "access_key_id": "AKIA...",
        "secret_access_key": "..."
      }
    },
    "state_backend": {
      "name": "Production State",
      "backend_type": "s3",
      "bucket": "my-terraform-state",
      "region": "us-east-1"
    },
    "workspace": {
      "name": "production",
      "source_repo_url": "https://github.com/yourorg/infra.git",
      "source_branch": "main",
      "source_root": "/",
      "state_key": "production/vpc"
    }
  }' \
  $FC_API/onboard | jq .

The response contains IDs for every resource created:

{
  "project": {"id": "..."},
  "credential_config": {"id": "...", "name": "AWS Production"},
  "state_backend_config": {"id": "...", "name": "Production State"},
  "workspace": {"id": "...", "name": "production"}
}

Save the workspace ID, then trigger a plan when you’re ready:

export WORKSPACE_ID=<workspace-id-from-response>

curl -s -X POST \
  -H "Authorization: Bearer $FC_KEY" \
  -H "Content-Type: application/json" \
  -d '{}' \
  $FC_API/workspaces/$WORKSPACE_ID/runs | jq .
export RUN_ID=<run-id-from-response>

Agent mode

If you run plans on your own infrastructure, use agent mode instead. This creates a project, workspace, and an API key for the agent binary:

curl -s -X POST \
  -H "Authorization: Bearer $FC_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "agent",
    "project_name": "Self-Hosted Infra",
    "workspace": {
      "name": "production",
      "source_repo_url": "https://github.com/yourorg/infra.git",
      "source_branch": "main"
    }
  }' \
  $FC_API/onboard | jq .

The response includes the agent API key (shown only once) and install instructions:

{
  "project": {"id": "..."},
  "workspace": {"id": "...", "name": "production"},
  "agent_key": {
    "id": "...",
    "name": "agent-production",
    "key": "fc_live_...",
    "masked_key": "fc_live_...a1b2"
  },
  "agent_install": "curl -sSfL https://install.forgecroft.com | sh\nexport FORGECROFT_API_URL=https://api.forgecroft.com\nexport FORGECROFT_API_KEY=fc_live_...\nforgecroft-agent"
}

Stream the logs

Poll the logs endpoint using the next_after cursor:

AFTER=0
while true; do
  RESP=$(curl -s -H "Authorization: Bearer $FC_KEY" \
    "$FC_API/runs/$RUN_ID/logs/json?after=$AFTER")

  echo "$RESP" | jq -r '.lines[]?.line // empty'

  NEW_AFTER=$(echo "$RESP" | jq -r '.next_after // empty')
  [ -n "$NEW_AFTER" ] && AFTER=$NEW_AFTER

  STATUS=$(curl -s -H "Authorization: Bearer $FC_KEY" \
    "$FC_API/runs/$RUN_ID" | jq -r '.status')
  case "$STATUS" in
    completed|failed|timed_out|rejected|cancelled|discarded)
      echo "Run finished: $STATUS"
      break ;;
  esac

  sleep 2
done

Check the result

curl -s -H "Authorization: Bearer $FC_KEY" \
  $FC_API/runs/$RUN_ID | jq '{status, added_count, changed_count, destroyed_count}'

Creating a CI-scoped API key

For CI/CD pipelines, create a narrowly-scoped key:

curl -s -X POST \
  -H "Authorization: Bearer $FC_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "CI Pipeline",
    "scope_type": "project",
    "scope_id": "'$PROJECT_ID'",
    "action_scope": "write",
    "scopes": ["trigger", "read"]
  }' \
  $FC_API/api-keys | jq .

This key can trigger plans and read results, but cannot approve runs, manage API keys, or access other projects. See API Keys for the full scope reference.


Step-by-step setup (advanced)

If you need more control over individual resources — for example, reusing an existing project or sharing credentials across workspaces — use the individual endpoints below.

Expand step-by-step setup

Verify your identity

curl -s -H "Authorization: Bearer $FC_KEY" $FC_API/whoami | jq .

Create a project

curl -s -X POST \
  -H "Authorization: Bearer $FC_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Infrastructure"}' \
  $FC_API/projects | jq .
export PROJECT_ID=<project-id-from-response>

Create a credential config

curl -s -X POST \
  -H "Authorization: Bearer $FC_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "AWS Production",
    "credential_type": "aws_static",
    "project_id": "'$PROJECT_ID'"
  }' \
  $FC_API/credential-configs | jq .
export CRED_ID=<credential-config-id>

Then store the actual secrets:

curl -s -X POST \
  -H "Authorization: Bearer $FC_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "data": {
      "access_key_id": "AKIA...",
      "secret_access_key": "..."
    }
  }' \
  $FC_API/credential-configs/$CRED_ID/secrets

Create a state backend config

curl -s -X POST \
  -H "Authorization: Bearer $FC_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production State",
    "backend_type": "s3",
    "bucket": "my-terraform-state",
    "region": "us-east-1",
    "credential_config_id": "'$CRED_ID'"
  }' \
  $FC_API/state-backend-configs | jq .
export BACKEND_ID=<state-backend-config-id>

Create a workspace

curl -s -X POST \
  -H "Authorization: Bearer $FC_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "production",
    "project_id": "'$PROJECT_ID'",
    "source_repo_url": "https://github.com/yourorg/infra.git",
    "source_branch": "main",
    "source_root": "/",
    "execution_target": "managed",
    "credential_config_ids": ["'$CRED_ID'"],
    "state_backend_config_id": "'$BACKEND_ID'",
    "state_key": "production/vpc"
  }' \
  $FC_API/workspaces | jq .
export WORKSPACE_ID=<workspace-id>

Trigger a plan

curl -s -X POST \
  -H "Authorization: Bearer $FC_KEY" \
  -H "Content-Type: application/json" \
  -d '{}' \
  $FC_API/workspaces/$WORKSPACE_ID/runs | jq .
export RUN_ID=<run-id>

Then follow the Stream the logs section above.

What’s next