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
- A Forgecroft account with an API key (create one in the console under Settings → API Keys, or via the OAuth flow)
- Cloud credentials (AWS access key, GCP service account, or Cloudflare API token)
- An S3 or GCS bucket for state storage
- A Git repository with OpenTofu or Terraform code
Set your API key:
export FC_API=https://api.forgecroft.com
export FC_KEY=fc_live_...
One-call setup (recommended)
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
- CLI Reference — manage runs from the command line
- Go SDK — build integrations in Go
- Stacks — manage multiple environments from one config
- Governance — add policies and approval workflows