# Farka workflow API

Base URL: `https://api.farka.ai`

The stable API automates Farka's managed training control plane: model discovery,
dataset intake, quoting, approved job launch, lifecycle monitoring, evaluation
evidence, and unlocked artifact delivery.

It does not expose River-style per-step optimizer primitives or promise a
Farka-managed inference endpoint. Deployment bundles instead serve authenticated
native and OpenAI-compatible inference routes from infrastructure you operate.

## Authentication

Owners and admins create workspace access tokens in **Settings → API access**.
Tokens:

- begin with `farka_`;
- are shown once;
- are stored only as a SHA-256 hash;
- belong to one workspace;
- expire after 90 days by default, with a supported range of 1 to 365 days;
- can carry `read` or `write` scope;
- can be revoked immediately.

The exact `read,provider` scope combination is reserved for provider workers.

Use standard Bearer authentication:

```sh
export FARKA_ACCESS_TOKEN="farka_..."
curl https://api.farka.ai/v1/models/presets \
  -H "Authorization: Bearer $FARKA_ACCESS_TOKEN"
```

`X-Farka-API-Key` is also accepted, but Bearer is recommended. Never put a
token in a URL, browser bundle, or source repository.

## Idempotency

Send a unique `Idempotency-Key` for every logical mutation. Reusing the same
key, method, route, workspace, and request body returns the original response.
Conflicting reuse returns HTTP `409`.

```sh
curl https://api.farka.ai/v1/quotes \
  -X POST \
  -H "Authorization: Bearer $FARKA_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: quote-sdk-expert-v1" \
  --data @quote.json
```

## Selected customer endpoints

| Method | Path | Purpose |
| --- | --- | --- |
| `GET` | `/v1/models/presets` | List curated models and training constraints. |
| `GET` | `/v1/models/iterations` | List the workspace's continuation chains and per-iteration deltas. |
| `GET` | `/v1/models/comparisons` | Rank continuations against rebuilds over one dataset lineage. |
| `GET` | `/v1/datasets` | List active-workspace datasets. |
| `POST` | `/v1/datasets/upload` | Validate, normalize, split, and store a dataset. |
| `POST` | `/v1/quotes` | Pin model, data, compute, export, retention, and price evidence. |
| `POST` | `/v1/jobs` | Create a job from an accepted workspace quote. |
| `POST` | `/v1/jobs/:id/launch` | Reserve credits and submit the approved workflow. |
| `GET` | `/v1/jobs/:id` | Read lifecycle, evaluation, settlement, and delivery status. |
| `GET` | `/v1/jobs/:id/iterations` | Read the continuation chain that contains one job. |
| `GET` | `/v1/jobs/:id/package` | Retrieve an unlocked package manifest after promotion. |

## Portable inference

The runnable deployment bundle includes the tuned weights, checksum-bound
runtime, TypeScript/Python clients, native `/invoke`, `/v1/models`, and
OpenAI-compatible `/v1/chat/completions`. These routes run in your environment;
Farka-managed hosted endpoints are not offered in the current launch.

## Continual training

Improving a model you already trained uses two request fields.

- `POST /v1/datasets/upload` accepts `lineageLabel` on a first upload to open a
  dataset lineage with a frozen holdout, or `lineageId` to add the next version
  to an existing one. Pass at most one. Content the lineage already holds
  returns `200` with that existing version instead of creating a duplicate. The
  lineage holdout seed is never returned.
- `POST /v1/quotes` accepts `continueFromJobId` to warm-start from a delivered
  model. The predecessor must be finished, have passed its quality gate, keep the
  same base model, method, LoRA rank, and objective, and still retain its adapter
  weights and adapter config. The run is then scored against that predecessor
  rather than the base model.

`GET /v1/models/iterations` returns the workspace's chains, each iteration's own
delta, and the cumulative movement from the first iteration's baseline.
`GET /v1/jobs/:id/iterations` returns `{ chain }` for a single job.

`GET /v1/models/comparisons` answers the question a chain cannot: whether
continuing is still beating a rebuild. It groups runs by dataset lineage rather
than by parentage, ranks them on their absolute holdout score, and ranks only
runs that scored the same holdout rows. Each lineage returns a `verdict` and a
signed `fromBaseAdvantage`, positive whenever rebuilding won.

## Response and error conventions

- JSON request bodies require `Content-Type: application/json`.
- Unknown request fields and unsupported query parameters are rejected.
- `400` means malformed or unsupported input.
- `401` or `403` means missing credentials or insufficient scope.
- `402` means credits or payment reconciliation block the operation.
- `409` means a lifecycle, evidence, capacity, or idempotency conflict.
- `429` means the caller exceeded a rate limit.
- `5xx` means a service or upstream failure. Retry only idempotent operations,
  preserving the same idempotency key for mutations.

## Token rotation

1. Create a new token with the minimum required scopes.
2. Update the calling workload.
3. Verify the new credential.
4. Revoke the old token.

Owners and admins activate API access in the browser application at
<https://app.farka.ai/#/settings>.
