# Forge Integration Quickstart

**For:** platform engineers wiring Claude, Kin, Cursor, n8n, custom agents, or any third-party software into Forge.  
**Base URL:** `https://forge.kin.team`  
**Updated:** 2026-08-11

---

## 60-second mental model

You are **not** rebuilding Forge inside your product.

1. Customer creates an API key in **Forge → Settings → API Keys** (`fk_live_...`).
2. Your product stores that key (one key = one company/tenant).
3. Your agent calls **one endpoint** with the user's words.
4. Forge creates/updates quotes, jobs, invoices, clients — with quality rules, duplicate guards, and approvals.

```
Your chat UI  →  POST /api/v1/agent/run  →  Q-#### / J-#### + links
```

Same design at 1 company or 10,000. Only the key changes.

---


## Agent laws & error recovery (read this)

**Laws (full JSON):** https://forge.kin.team/api/v1/agent-laws · **v2.0.0 Product Law Balanced**  
**Discovery:** https://forge.kin.team/.well-known/api.json · **OpenAPI:** https://forge.kin.team/api/v1/openapi.yaml

1. **Never create to update** — `forge_update_job` / `forge_revise_invoice` / `forge_update_client` on the same id/number.
2. **Sent unpaid invoices are editable** — same INV-####; do not invent INV-0040 or INV-####-REV.
3. **Errors are actionable** — body includes `recovery.suggestedTool` + `recovery.suggestedArgs`. Call that. Do not freestyle.
4. **Create-only thin tool hosts will duplicate** — register `forge_agent` OR full list+get+update+revise set.
5. **Product Law Balanced (server constitution on commercial creates)** — same for UI, REST, MCP, native agent:
   - Clear email/phone/name → **reuse client** (no twin).
   - Site in fields or notes → **link/create Property** (`propertyId` / `propertyAddress` / `propertyLabel`).
   - Ambiguous multi-match → **stop and ask** (never `candidates[0]`).
   - One open invoice per job → **revise**, do not mint a second INV.
   - `force: true` is exception-only; pass `forceReason` (audited). Prefer recovery tools.

Example error shape:

```json
{
  "ok": false,
  "code": "DUPLICATE_DETECTED",
  "message": "...",
  "existing": { "jobNumber": "J-0042" },
  "recovery": {
    "suggestedTool": "forge_update_job",
    "suggestedArgs": { "id": "J-0042" },
    "doNot": ["Do not call forge_create_job again"]
  },
  "_agent": { "next": "Call forge_update_job with {\"id\":\"J-0042\"}" }
}
```


## Path A — Native agent (recommended)

### Request

```http
POST https://forge.kin.team/api/v1/agent/run
Authorization: Bearer fk_live_...
Content-Type: application/json
Idempotency-Key: 8f2c1a6e-...
```

```json
{
  "message": "Create a quote for Acme Corp drywall repairs at 12 Main St for $2400. Full scope in the line detail. Do not send.",
  "dryRun": false,
  "conversationId": null,
  "autoSend": false
}
```

### curl

```bash
curl -X POST https://forge.kin.team/api/v1/agent/run \
  -H "Authorization: Bearer fk_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"message":"Quote Acme drywall $2400. Do not send.","autoSend":false}'
```

### Client requirements

| Requirement | Value |
|-------------|--------|
| Timeout | **≥ 120 seconds** |
| Auth | Bearer API key or OAuth access token |
| Default `autoSend` | `false` |

### Response (shape)

- `ok`, `runId`, `conversationId`
- `status`: `completed` | `needs_approval` | `failed` | `dry_run`
- `summary` — show this to the human
- `artifacts[]` — `{ type, id, number, url }`
- `needsApproval[]` — park until user confirms
- `actions[]` — tool-level trace

### Approvals

```http
POST /api/v1/agent/approvals/{id}/approve
POST /api/v1/agent/approvals/{id}/reject
```

### Register one tool in your platform

```
name: run_forge_agent
args: message (string), conversationId?, dryRun?, autoSend?
maps_to: POST /api/v1/agent/run
```

**System prompt blurb:**

> For any Forge CRM work (clients, quotes, jobs, invoices, updates), call `run_forge_agent` with the user's words. Do not invent line-item JSON. Do not create a second job to apply an edit.

Full detail: [FORGE_AGENT_API.md](./FORGE_AGENT_API.md)

---

## Path B — MCP

Discovery: `GET https://forge.kin.team/.well-known/mcp.json`  
Server: `https://forge.kin.team/api/mcp`

Default multi-step tool: **`forge_agent`**.  
Full CRUD also available (`forge_list_jobs`, `forge_update_job`, `forge_update_client`, …) — 67 tools.

Auth: OAuth 2.1 or API key depending on your MCP host.

---

## Path C — REST v1

- Spec: `GET https://forge.kin.team/api/v1/openapi.yaml`
- Guide for quote quality: `GET https://forge.kin.team/api/v1/agent-guide`
- Machine discovery: `GET https://forge.kin.team/.well-known/api.json`

Use REST when you need a custom UI or ETL — not as the default for chat agents.

### Critical field aliases

| You send | Forge stores |
|----------|----------------|
| `email` | `billingEmail` |
| `phone` | `billingPhone` |
| `address` | `billingAddress` |

Job/quote get+update accept **UUID or** `J-0042` / `Q-0016`.

### Duplicate job guard

`POST /jobs` returns `DUPLICATE_DETECTED` when the same client + PO / similar title already exists. **Update the existing job** — do not create another.

Tool matrix: [KIN_FORGE_TOOLS.md](./KIN_FORGE_TOOLS.md)

---

## Platform checklist

1. [ ] Store per-tenant `fk_live_...` securely  
2. [ ] Register **`run_forge_agent`** (or MCP `forge_agent`) as default  
3. [ ] 120s+ timeout on agent runs  
4. [ ] Surface `summary`, artifact URLs, and approval prompts  
5. [ ] If you also ship thin tools, include **list + get + update** for jobs/clients/quotes — create-only causes duplicates  
6. [ ] Never default `autoSend: true`  
7. [ ] Hit `GET /api/v1/health` for liveness  

---

## Discovery URLs (bookmark these)

| Resource | URL |
|----------|-----|
| Developer hub | https://forge.kin.team/developers |
| API discovery JSON | https://forge.kin.team/.well-known/api.json |
| MCP discovery | https://forge.kin.team/.well-known/mcp.json |
| OpenAPI | https://forge.kin.team/api/v1/openapi.yaml |
| llms.txt | https://forge.kin.team/llms.txt |
| AI product page | https://forge.kin.team/ai-agents |

---

## Support

hello@kin.team · forge.kin.team

## MCP idempotency (v1.2)

Mutating MCP tools accept **`idempotencyKey`** (also `idempotency_key` or `_meta.idempotencyKey`):

```json
{
  "name": "forge_create_job",
  "arguments": {
    "clientId": "…",
    "title": "Drywall repair",
    "idempotencyKey": "8f2c1a6e-your-uuid"
  }
}
```

- Same key + success → **replayed for 24h** (no second J-/INV-/Q- number)
- Errors are **not** cached — fix args and retry with the same key
- REST equivalent: header `Idempotency-Key: <uuid>` on POST creates and `POST /api/v1/agent/run`

## REST error envelope (v1.2 + Product Law codes)

All `/api/v1/*` JSON errors include:

```json
{
  "ok": false,
  "code": "DUPLICATE_DETECTED",
  "message": "…",
  "hint": "…",
  "existing": { "jobNumber": "J-0042" },
  "recovery": {
    "suggestedTool": "forge_update_job",
    "suggestedArgs": { "id": "J-0042" },
    "doNot": ["Do not call forge_create_job again"]
  },
  "_agent": {
    "next": "Call forge_update_job with {\"id\":\"J-0042\"}",
    "lawsUrl": "https://forge.kin.team/api/v1/agent-laws"
  },
  "error": { "code": "DUPLICATE_DETECTED", "message": "…" }
}
```

On any `ok: false`, call `recovery.suggestedTool` with `recovery.suggestedArgs`. Never freestyle.
