Skip to main content

REST API

Friday Dev exposes a RESTful API for programmatic access.

Base URL

http://localhost:3000/api

For production:

https://your-domain.com/api

Authentication

API Key

Include your API key in the header:

Authorization: Bearer YOUR_API_KEY

Getting an API Key

friday-dev config get apiKey
# Or generate new:
friday-dev config set apiKey $(openssl rand -hex 32)

Tasks

List Tasks

GET /api/tasks

Query Parameters:

ParameterTypeDescription
statusstringFilter by status
prioritystringFilter by priority
project_idstringFilter by project
limitnumberMax results (default 50)
offsetnumberSkip results

Response:

{
"tasks": [
{
"id": 123,
"title": "Add authentication",
"description": "Implement JWT auth",
"status": "in_progress",
"priority": "high",
"labels": ["backend", "security"],
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T14:20:00Z"
}
],
"total": 45,
"limit": 50,
"offset": 0
}

Get Task

GET /api/tasks/:id

Response:

{
"id": 123,
"title": "Add authentication",
"description": "Implement JWT auth",
"status": "in_progress",
"priority": "high",
"labels": ["backend", "security"],
"project_id": "proj_abc123",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T14:20:00Z",
"agent_runs": [
{
"id": "run_xyz",
"agent": "friday",
"status": "completed",
"started_at": "2024-01-15T11:00:00Z",
"completed_at": "2024-01-15T11:15:00Z"
}
]
}

Create Task

POST /api/tasks

Request Body:

{
"title": "Add login page",
"description": "Create a responsive login page",
"priority": "high",
"labels": ["frontend", "auth"],
"project_id": "proj_abc123"
}

Response:

{
"id": 124,
"title": "Add login page",
"description": "Create a responsive login page",
"status": "backlog",
"priority": "high",
"labels": ["frontend", "auth"],
"project_id": "proj_abc123",
"created_at": "2024-01-15T15:00:00Z"
}

Update Task

PATCH /api/tasks/:id

Request Body:

{
"status": "done",
"priority": "medium"
}

Delete Task

DELETE /api/tasks/:id

Response:

{
"success": true
}

Projects

List Projects

GET /api/projects

Response:

{
"projects": [
{
"id": "proj_abc123",
"name": "My App",
"path": "/path/to/project",
"created_at": "2024-01-01T00:00:00Z"
}
]
}

Get Project

GET /api/projects/:id

Create Project

POST /api/projects

Request Body:

{
"name": "New Project",
"path": "/path/to/project",
"git_url": "https://github.com/user/repo"
}

Delete Project

DELETE /api/projects/:id

Agent Runs

Run Agent

POST /api/tasks/:id/run

Request Body:

{
"agent": "friday",
"autonomy": "workspace-write",
"branch": "feature/auth"
}

Response:

{
"run_id": "run_xyz789",
"task_id": 123,
"agent": "friday",
"status": "running",
"started_at": "2024-01-15T16:00:00Z"
}

Get Run Status

GET /api/runs/:run_id

Response:

{
"id": "run_xyz789",
"task_id": 123,
"agent": "friday",
"status": "completed",
"started_at": "2024-01-15T16:00:00Z",
"completed_at": "2024-01-15T16:15:00Z",
"output": {
"files_modified": ["src/auth.ts", "src/routes.ts"],
"lines_added": 150,
"lines_removed": 20
}
}

Get Run Logs

GET /api/runs/:run_id/logs

Query Parameters:

ParameterTypeDescription
sincetimestampLogs after this time
limitnumberMax log entries

Response:

{
"logs": [
{
"timestamp": "2024-01-15T16:00:01Z",
"level": "info",
"message": "Reading task description..."
},
{
"timestamp": "2024-01-15T16:00:05Z",
"level": "info",
"message": "Analyzing codebase..."
}
]
}

Stop Run

POST /api/runs/:run_id/stop

Code Review

Review Task Output

POST /api/tasks/:id/review

Request Body:

{
"action": "approve"
}

Actions: approve, reject, request_changes

Review PR

POST /api/review/pr

Request Body:

{
"repo": "owner/repo",
"pr_number": 123,
"agent": "claude"
}

Labels

List Labels

GET /api/labels

Create Label

POST /api/labels

Request Body:

{
"name": "urgent",
"color": "#ff0000"
}

Error Responses

All errors follow this format:

{
"error": {
"code": "NOT_FOUND",
"message": "Task not found",
"details": {}
}
}

Error Codes

CodeHTTP StatusDescription
BAD_REQUEST400Invalid request
UNAUTHORIZED401Missing/invalid auth
FORBIDDEN403Access denied
NOT_FOUND404Resource not found
CONFLICT409Resource conflict
RATE_LIMITED429Too many requests
INTERNAL_ERROR500Server error

Rate Limiting

  • Default: 100 requests/minute
  • Authenticated: 1000 requests/minute

Headers:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1705334400

Pagination

List endpoints support pagination:

GET /api/tasks?limit=20&offset=40

Response includes:

{
"total": 100,
"limit": 20,
"offset": 40
}

Examples

cURL

# Create task
curl -X POST http://localhost:3000/api/tasks \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"title": "New task", "priority": "high"}'

# Run agent
curl -X POST http://localhost:3000/api/tasks/123/run \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"agent": "gemini"}'

JavaScript

const API_BASE = 'http://localhost:3000/api';
const API_KEY = 'YOUR_API_KEY';

async function createTask(title, priority) {
const response = await fetch(`${API_BASE}/tasks`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${API_KEY}`
},
body: JSON.stringify({ title, priority })
});
return response.json();
}

Python

import requests

API_BASE = 'http://localhost:3000/api'
API_KEY = 'YOUR_API_KEY'

def create_task(title, priority):
response = requests.post(
f'{API_BASE}/tasks',
headers={'Authorization': f'Bearer {API_KEY}'},
json={'title': title, 'priority': priority}
)
return response.json()

Next Steps