List tasks for a project
curl --request GET \
--url https://api.example.com/api/tasks \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.example.com/api/tasks"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.example.com/api/tasks', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/api/tasks",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/api/tasks"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.example.com/api/tasks")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/tasks")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body"<unknown>"API Reference
REST Overview
Complete reference for Forge’s REST API
GET
/
api
/
tasks
List tasks for a project
curl --request GET \
--url https://api.example.com/api/tasks \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.example.com/api/tasks"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.example.com/api/tasks', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/api/tasks",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/api/tasks"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.example.com/api/tasks")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/tasks")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body"<unknown>"Overview
Forge provides a comprehensive REST API for programmatic access to all features. Build integrations, automate workflows, or create custom tooling.Base URL:
http://localhost:8887/api (default)Authentication
API Keys (Coming Soon)
Currently, Forge runs locally without authentication. API key authentication will be added for remote deployments.# Future API key usage
curl -H "Authorization: Bearer YOUR_API_KEY" \
http://localhost:8887/api/projects
GitHub OAuth
For web UI access, GitHub OAuth is used. API access uses session cookies.Base URL
# Local development (default)
BASE_URL=http://localhost:8887
# Custom port (if configured)
BASE_URL=http://localhost:9000
# Remote deployment
BASE_URL=https://forge.yourdomain.com
Response Format
Success Response
{
"success": true,
"data": {
// Response data
},
"meta": {
"timestamp": "2024-01-15T10:30:00Z",
"version": "0.4.4"
}
}
Error Response
{
"success": false,
"error": {
"code": "TASK_NOT_FOUND",
"message": "Task with id 'abc123' not found",
"details": {}
},
"meta": {
"timestamp": "2024-01-15T10:30:00Z"
}
}
Error Codes
| Code | HTTP Status | Description |
|---|---|---|
VALIDATION_ERROR | 400 | Invalid request parameters |
UNAUTHORIZED | 401 | Authentication required |
FORBIDDEN | 403 | Insufficient permissions |
NOT_FOUND | 404 | Resource not found |
CONFLICT | 409 | Resource conflict |
RATE_LIMIT | 429 | Too many requests |
INTERNAL_ERROR | 500 | Server error |
Pagination
List endpoints support pagination:GET /api/tasks?page=1&limit=20
{
"success": true,
"data": [...],
"pagination": {
"page": 1,
"limit": 20,
"total": 156,
"pages": 8,
"hasNext": true,
"hasPrev": false
}
}
page: Page number (1-indexed)limit: Items per page (max: 100)
Filtering & Sorting
Filtering
# Filter by status
GET /api/tasks?status=in_progress
# Multiple filters
GET /api/tasks?status=pending&priority=high
# Filter by label
GET /api/tasks?labels=feature,backend
Sorting
# Sort by created date (descending)
GET /api/tasks?sort=-created_at
# Sort by priority (ascending)
GET /api/tasks?sort=priority
# Multiple sort fields
GET /api/tasks?sort=-priority,created_at
-= Descending- No prefix = Ascending
API Endpoints
Core Resources
Projects
Manage Forge projects
GET /api/projectsPOST /api/projectsGET /api/projects/:idPATCH /api/projects/:idDELETE /api/projects/:id
Tasks
Manage tasks and workflows
GET /api/tasksPOST /api/tasksGET /api/tasks/:idPATCH /api/tasks/:idDELETE /api/tasks/:id
Attempts
Manage task attempts
GET /api/attemptsPOST /api/attemptsGET /api/attempts/:idDELETE /api/attempts/:id
Processes
Monitor running processes
GET /api/processesGET /api/processes/:idPOST /api/processes/:id/cancel
Quick Examples
Get All Tasks
curl http://localhost:8887/api/tasks
Create New Task
curl -X POST http://localhost:8887/api/tasks \
-H "Content-Type: application/json" \
-d '{
"title": "Add user authentication",
"description": "Implement JWT-based auth",
"projectId": "project-123",
"llm": "claude",
"priority": "high",
"labels": ["feature", "backend"]
}'
Update Task Status
curl -X PATCH http://localhost:8887/api/tasks/task-123 \
-H "Content-Type: application/json" \
-d '{
"status": "in_progress"
}'
Start Task Attempt
curl -X POST http://localhost:8887/api/attempts \
-H "Content-Type: application/json" \
-d '{
"taskId": "task-123",
"llm": "claude",
"options": {}
}'
Rate Limiting
Current limits (local deployment):No rate limits for local usage
- 60 requests per minute per IP
- 1000 requests per hour per user
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1642248000
Webhooks
Subscribe to Forge events:POST /api/webhooks
{
"url": "https://your-server.com/webhook",
"events": ["task.created", "task.completed", "attempt.failed"],
"secret": "your-webhook-secret"
}
{
"event": "task.completed",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
"taskId": "task-123",
"status": "completed",
"duration": 322000
},
"signature": "sha256=abc123..."
}
WebSocket API
Real-time updates via WebSocket:const ws = new WebSocket('ws://localhost:8887/ws');
ws.onopen = () => {
// Subscribe to task updates
ws.send(JSON.stringify({
type: 'subscribe',
channel: 'tasks',
taskId: 'task-123'
}));
};
ws.onmessage = (event) => {
const update = JSON.parse(event.data);
console.log('Task update:', update);
};
{
"type": "task.status_changed",
"taskId": "task-123",
"status": "in_progress",
"timestamp": "2024-01-15T10:30:00Z"
}
SDK Libraries
JavaScript/TypeScript
npm install @automagik/forge-sdk
import { ForgeClient } from '@automagik/forge-sdk';
const forge = new ForgeClient({
baseUrl: 'http://localhost:8887'
});
// Create task
const task = await forge.tasks.create({
title: 'Add authentication',
projectId: 'project-123',
llm: 'claude'
});
// Start attempt
const attempt = await forge.attempts.create({
taskId: task.id,
llm: 'claude'
});
Python
pip install automagik-forge
from automagik_forge import ForgeClient
forge = ForgeClient(base_url='http://localhost:8887')
# Create task
task = forge.tasks.create(
title='Add authentication',
project_id='project-123',
llm='claude'
)
# Start attempt
attempt = forge.attempts.create(
task_id=task.id,
llm='claude'
)
API Versioning
Current version: v1 (implicit) Future versioning:# Explicit version in URL
GET /api/v1/tasks
# Or via header
GET /api/tasks
Accept: application/vnd.forge.v1+json
OpenAPI Specification
Download the full OpenAPI spec:# JSON format
curl http://localhost:8887/api/openapi.json > forge-api.json
# YAML format
curl http://localhost:8887/api/openapi.yaml > forge-api.yaml
- Postman
- Insomnia
- Swagger UI
- API clients
Testing the API
Using cURL
# Set base URL
BASE=http://localhost:8887/api
# Get all tasks
curl $BASE/tasks
# Create task
curl -X POST $BASE/tasks \
-H "Content-Type: application/json" \
-d @task.json
# Pretty print JSON
curl $BASE/tasks | jq
Using HTTPie
# Install HTTPie
brew install httpie
# Get tasks (cleaner syntax)
http localhost:8887/api/tasks
# Create task
http POST localhost:8887/api/tasks \
title="Add feature" \
projectId="project-123" \
llm="claude"
Using Postman
- Import OpenAPI spec:
http://localhost:8887/api/openapi.json - Set environment variable:
baseUrl = http://localhost:8887 - Start making requests
Best Practices
Use SDK Libraries
Use official SDKs instead of raw HTTP:SDKs handle auth, retries, typing
// Good ✅
forge.tasks.create({...})
// Avoid ❌
fetch('/api/tasks', {...})
Handle Errors
try {
const task = await forge.tasks.create({...});
} catch (error) {
if (error.code === 'VALIDATION_ERROR') {
// Handle validation
} else if (error.code === 'NOT_FOUND') {
// Handle not found
}
}
Use Pagination
Don’t fetch all at once:
// Good ✅
const tasks = await forge.tasks.list({
page: 1,
limit: 20
});
// Bad ❌
const allTasks = await forge.tasks.list({
limit: 10000
});
Cache Responses
const cache = new Map();
async function getTask(id) {
if (cache.has(id)) {
return cache.get(id);
}
const task = await forge.tasks.get(id);
cache.set(id, task);
return task;
}
Next Steps
Projects API
Manage Forge projects
Tasks API
Create and manage tasks
Attempts API
Execute tasks with AI agents
MCP Tools
Use Forge from AI coding agents
Was this page helpful?

