View as Markdown

Integration Quickstart

This guide walks through a complete integration: creating a PAT, listing repositories, starting a runner, monitoring it, and running a routine now.

Prerequisites

  • A Forkline account with at least one repository connected
  • curl or any HTTP client

Client Libraries

The Forkline API is a standard REST API. You can use any HTTP client in your language of choice. Below are examples in Python and TypeScript alongside the curl commands used throughout this guide.

Python

import requests

BASE_URL = "https://api.forkline.dev/v1"
headers = {"Authorization": f"Bearer {TOKEN}"}

# List repositories
resp = requests.get(f"{BASE_URL}/repositories", headers=headers)
repos = resp.json()["repositories"]

# Start a runner
resp = requests.post(
    f"{BASE_URL}/repositories/{repo_id}/runners",
    headers={**headers, "Content-Type": "application/json"},
    json={"name": "my-runner", "size": "basic"},
)
runner = resp.json()

# Poll runner status
resp = requests.get(f"{BASE_URL}/runners/{runner['id']}", headers=headers)
print(resp.json()["status"])

TypeScript

const BASE_URL = "https://api.forkline.dev/v1";
const headers = { Authorization: `Bearer ${TOKEN}` };

// List repositories
const listResp = await fetch(`${BASE_URL}/repositories`, { headers });
const { repositories } = await listResp.json();

// Start a runner
const startResp = await fetch(`${BASE_URL}/repositories/${repoId}/runners`, {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({ name: "my-runner", size: "basic" }),
});
const runner = await startResp.json();

// Poll runner status
const statusResp = await fetch(`${BASE_URL}/runners/${runner.id}`, { headers });
const { status } = await statusResp.json();

Info: The official Forkline CLI provides a command-line interface for all API operations. No SDK packages (npm, crates.io) are published yet — the examples above use plain HTTP clients. The OpenAPI specification can be used to generate typed clients with tools like openapi-generator, Hey API (@hey-api/openapi-ts for TypeScript), or oapi-codegen for Go.

Step 1: Create a Personal Access Token

  1. Log in to the Forkline web application
  2. Go to Settings → API Tokens
  3. Click Create Token
  4. Select the scopes you need (for this guide: repositories:read, runners:read, runners:write, routines:read, routines:execute)
  5. Copy the token — it is shown only once

Export it for the examples below:

export FORKLINE_TOKEN="fl_pat_v1_..."

See Authentication for full details on scopes and token management.

Step 2: List Your Repositories

curl -H "Authorization: Bearer $FORKLINE_TOKEN" \
  https://api.forkline.dev/v1/repositories

Response:

{
  "repositories": [
    {
      "id": "a1b2c3d4-...",
      "name": "my-project",
      "owner": "octocat",
      "repository_url": "https://github.com/octocat/my-project",
      "connector_id": "f0e1d2c3-...",
      "default_runner_size": "basic",
      "trigger_policy": "open",
      "allowed_users": [],
      "created_at": "2026-01-15T10:30:00Z",
      "updated_at": "2026-09-01T08:00:00Z"
    }
  ],
  "total": 1,
  "offset": 0,
  "limit": 50,
  "has_more": false
}

Save the repository id for the next steps.

Step 3: Start a Runner

curl -X POST \
  -H "Authorization: Bearer $FORKLINE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "api-test-runner", "size": "basic"}' \
  https://api.forkline.dev/v1/repositories/<repository_id>/runners

Response (201 Created):

{
  "id": "r4n5n6r7-...",
  "short": "r4n5",
  "repository_id": "a1b2c3d4-...",
  "name": "api-test-runner",
  "status": "starting",
  "source": "manual",
  "size": "basic",
  "created_at": "2026-09-18T14:20:00Z"
}

Note: Starting a runner requires sufficient credits. If credits are insufficient, the API returns 402 INSUFFICIENT_CREDITS.

Step 4: Monitor the Runner

Poll the runner status:

curl -H "Authorization: Bearer $FORKLINE_TOKEN" \
  https://api.forkline.dev/v1/runners/<runner_id>

Check the event history:

curl -H "Authorization: Bearer $FORKLINE_TOKEN" \
  https://api.forkline.dev/v1/runners/<runner_id>/events

Response:

{
  "events": [
    {
      "id": "evt-...",
      "runner_id": "r4n5n6r7-...",
      "event_type": "started",
      "new_status": "running",
      "details": {},
      "created_at": "2026-09-18T14:20:30Z"
    }
  ]
}

Step 5: Run a Routine Now

Run now requires the routines:execute scope and a published or disabled routine. Creating and publishing need routines:write. A webhook routine must select one of your repositories (replace octocat/my-project below), otherwise create answers 422. Create one first. on.webhook: {} means the default token authentication, and the response contains the secret once. (That secret is for the systems that call the webhook URL; Run now does not use it.)

curl -X POST \
  -H "Authorization: Bearer $FORKLINE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "deploy-staging",
    "spec": {
      "on": {"webhook": {}},
      "repositories": {"include": [{"name": "octocat/my-project"}]},
      "agent": {"prompt": "Deploy {{ repository.fullName }} to staging. Note: {{ payload.text }}"}
    }
  }' \
  https://api.forkline.dev/v1/routines

curl -X POST -H "Authorization: Bearer $FORKLINE_TOKEN" \
  https://api.forkline.dev/v1/routines/<routine_id>/publish

The payload you send is available in the prompt as payload.*, as it is for a webhook call. The routine definition is described under POST /v1/routines. Preview first with "dry_run": true: it writes nothing and shows what would start and the most it can cost.

curl -X POST \
  -H "Authorization: Bearer $FORKLINE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"payload": {"text": "Deploy to staging"}}' \
  https://api.forkline.dev/v1/routines/<routine_id>/run

Response:

{
  "dry_run": false,
  "event_id": "0000000e-0000-4000-8000-000000000001",
  "targets": [
    {
      "repository": {"id": "0000000a-0000-4000-8000-000000000001", "full_name": "octocat/my-project"},
      "outcome": "task_created",
      "task_id": "t1a2b3c4-...",
      "session_url": "/sessions/t1a2b3c4-...",
      "reason": "Started a run for `octocat/my-project`."
    }
  ],
  "estimate": {"runs": 1, "credits_per_run_max": 30, "credits_max": 30},
  "task_ids": ["t1a2b3c4-..."],
  "session_urls": ["/sessions/t1a2b3c4-..."]
}

See POST /v1/routines/{id}/run for schedule and event routines, subsets and errors.

Step 6: Poll Routine Tasks

Check the tasks created by the routine:

curl -H "Authorization: Bearer $FORKLINE_TOKEN" \
  https://api.forkline.dev/v1/routines/<routine_id>/tasks

Response:

{
  "tasks": [
    {
      "id": "t1a2b3c4-...",
      "status": "running",
      "task_type": "generic",
      "repository_url": "https://github.com/octocat/my-project",
      "created_at": "2026-09-18T14:25:00Z",
      "completed_at": null,
      "error_message": null
    }
  ]
}

Poll this endpoint until status is completed or failed.

What’s Next

  • Endpoints — full reference with request/response examples
  • Authentication — scopes, token management, best practices
  • Errors — error codes and handling patterns

What’s Not in the Public API

The following features are only available through the Forkline web application and are not exposed in the public API v1:

  • Billing write operations (subscription changes, credit purchases)
  • API token self-management via browser session (create/revoke tokens via the web UI or app-domain API)
  • Connector configuration (GitHub/GitLab/Forgejo setup)
  • Custom AI provider configuration and OpenCode auth setup

These are tracked as separate enhancement requests.