Build on Forge
Connect any AI agent or app to field-service CRM — quotes, jobs, invoices, clients — without rebuilding our product. One preferred call. Full REST + MCP when you need control.
Three integration paths
Pick the lightest path that fits your host. Chat agents should almost always use Path 1.
1. Native agent
One HTTP tool. Send the user's words. Forge runs multi-step ops, quality rules, and duplicate guards.
POST /api/v1/agent/run
2. Model Context Protocol
145 live tools — clients through invoices. Default multi-step: forge_agent.
/.well-known/mcp.json
3. REST API v1
Full OpenAPI for UIs, ETL, and automations. Same auth, same tenant isolation.
/api/v1/openapi.yaml
5-minute quickstart
- 1
Create a tenant API key
In Forge: Settings → API Keys. Copy
fk_live_.... One key = one company. Store it in your secret vault — never in the client. - 2
Register one tool on your platform
Name it
run_forge_agent. Map to the request below. Client timeout ≥ 120s.POST https://forge.kin.team/api/v1/agent/run Authorization: Bearer fk_live_... Content-Type: application/json Idempotency-Key: <uuid> { "message": "Quote Acme Corp drywall unit 12 $2400. Full scope in detail. Do not send.", "dryRun": false, "conversationId": null, "autoSend": false } - 3
System prompt (copy-paste)
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 or quote to apply an edit — update instead. Never set autoSend true unless the user explicitly asks to send. Show the human: summary, artifact links, and any needsApproval items. - 4
Handle the response
{ "ok": true, "runId": "...", "status": "completed | needs_approval | failed | dry_run", "summary": "Created quote Q-0016 for Acme…", "artifacts": [{ "type": "quote", "number": "Q-0016", "url": "..." }], "needsApproval": [], "actions": [{ "tool": "forge_create_quote", "ok": true }] }Approvals:
POST /api/v1/agent/approvals/{id}/approveor…/reject. Poll:GET /api/v1/agent/runs/{runId}.
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}'Authentication
API keys (server-to-server)
Create in Settings → API Keys. Pass as Bearer token on every request.
Authorization: Bearer fk_live_...Keys are tenant-scoped. Scopes are checked per endpoint (jobs:write, quotes:write, …).
OAuth 2.1 + PKCE
For third-party apps and interactive agent hosts.
- Register:
POST /oauth/register - Authorize:
/oauth/authorize - Token:
POST /oauth/token - Metadata: oauth-authorization-server
Rules that prevent broken agents
Avoid: Ship only forge_create_job
Do: Also ship list/get/update — or just forge_agent
Create-only tools cause duplicate jobs when users say “update it”.
Avoid: Chain 8 thin tools for one quote
Do: One POST /agent/run with the user message
Quality rules, PO guards, and line-item standards live server-side.
Avoid: Send root field email and wonder why it’s null
Do: Send email (alias) or billingEmail
Forge accepts friendly aliases; canonical store is billingEmail.
Avoid: autoSend: true in tests / default
Do: autoSend: false unless user confirms
Outbound email and client-facing sends need explicit intent.
Avoid: 30s HTTP timeout on agent/run
Do: ≥ 120s
Multi-step runs can include model + several tools.
MCP
Remote MCP server for Claude Desktop, Cursor, and other hosts. Tool list is generated from the live registry — never a stale subset.
{
"mcpServers": {
"forge": {
"type": "http",
"url": "https://forge.kin.team/api/mcp"
}
}
}Discovery: https://forge.kin.team/.well-known/mcp.json · 145 tools generated from the live registry · Prefer forge_agent for multi-step; use forge_list_jobs / forge_update_job / forge_update_quote for direct edits.
Native agent (1)
- forge_agent
Clients & contacts (9)
- forge_create_client
- forge_create_contact
- forge_delete_client
- forge_get_client
- forge_list_clients
- forge_list_contacts
- forge_merge_clients
- forge_update_client
- forge_update_contact
Properties (6)
- forge_assign_property_contact
- forge_create_property
- forge_delete_property
- forge_get_property
- forge_list_property_contacts
- forge_update_property
Quotes & deposits (14)
- forge_approve_quote
- forge_convert_quote_to_job
- forge_create_quote
- forge_decline_quote
- forge_delete_quote
- forge_duplicate_quote
- forge_get_quote
- forge_list_quotes
- forge_mark_quote_sent
- forge_request_deposit
- forge_send_quote
- forge_send_quote_sms
- forge_sync_job_from_quote
- forge_update_quote
Jobs, crew & photos (21)
- forge_add_job_cost
- forge_assign_crew
- forge_attach_job_photo
- forge_book_job
- forge_complete_job
- forge_convert_job_to_invoice
- forge_convert_quote_to_job
- forge_create_job
- forge_delete_job
- forge_get_job
- forge_get_job_costs
- forge_get_transitions
- forge_list_crew
- forge_list_job_photos
- forge_list_jobs
- forge_list_unscheduled_jobs
- forge_mark_job_photos
- forge_remove_job_cost
- forge_sync_job_from_quote
- forge_unassign_crew
- forge_update_job
Visits / schedule / crew (12)
- forge_assign_crew
- forge_complete_visit
- forge_create_site_visit
- forge_create_visit
- forge_get_availability
- forge_get_schedule
- forge_list_crew
- forge_list_unscheduled_jobs
- forge_list_visits
- forge_reschedule_visit
- forge_unassign_crew
- forge_update_visit
Invoices, payments & AR (22)
- forge_batch_send_invoices
- forge_convert_job_to_invoice
- forge_create_invoice
- forge_delete_invoice
- forge_get_ar_summary
- forge_get_invoice
- forge_get_invoice_public_link
- forge_get_payment
- forge_list_invoices
- forge_list_overdue_invoices
- forge_list_payments
- forge_mark_invoice_sent
- forge_publish_invoice_qb
- forge_record_payment
- forge_reopen_invoice
- forge_revise_invoice
- forge_send_invoice
- forge_send_payment_reminder
- forge_sync_invoice_qb_dates
- forge_update_invoice
- forge_void_invoice
- forge_void_payment
Change orders (6)
- forge_create_change_order
- forge_get_change_order
- forge_list_change_orders
- forge_send_change_order
- forge_send_change_order_sms
- forge_update_change_order
Time, payroll & team (16)
- forge_approve_time_correction
- forge_approve_timesheets
- forge_create_time_entry
- forge_create_time_off
- forge_decide_time_off
- forge_delete_time_entry
- forge_export_payroll
- forge_get_payroll_period
- forge_get_time_entry
- forge_list_payroll_periods
- forge_list_team
- forge_list_time_corrections
- forge_list_time_off
- forge_list_timesheets
- forge_lock_pay_period
- forge_update_time_entry
Catalog, tax & custom fields (13)
- forge_create_custom_field
- forge_create_service
- forge_create_tax_rate
- forge_get_custom_field_values
- forge_get_service
- forge_get_tax_rate
- forge_list_custom_fields
- forge_list_services
- forge_list_tax_rates
- forge_match_service
- forge_set_custom_field_values
- forge_update_service
- forge_update_tax_rate
Receipts (4)
- forge_approve_receipt
- forge_link_receipt
- forge_list_receipts
- forge_update_receipt
Search, memory, trash (6)
- forge_get_overview
- forge_list_trash
- forge_recall
- forge_remember
- forge_restore
- forge_search
Agent footguns (fixed in product — still document for hosts)
- Description-only quote updates keep existing prices (merge by line id/index). Do not recreate Q-#### to clean wording.
- Dirty money strings like
$2.80/sq ftparse on create/update. - Missing thin tools on a host ≠ missing Forge capability — register
forge_agentor the full list/get/update set. - Invoice edits:
forge_revise_invoice/forge_update_invoiceon the same INV-#### — never a second create.
REST highlights
Full contract in openapi.yaml. Common writes:
| Method | Path | Purpose |
|---|---|---|
| POST | /api/v1/agent/run | Native agent (preferred) |
| GET | /api/v1/agent-laws | Mandatory create-vs-update contract |
| GET | /api/v1/agent-guide | Quote quality rules |
| GET/POST | /api/v1/clients | List / create (email alias OK) |
| PATCH | /api/v1/clients/:id | Update client + primary contact sync |
| GET/POST | /api/v1/jobs | List / create (duplicate guard) |
| PATCH | /api/v1/jobs/:id | Update — UUID or J-#### (+ clientId/propertyId) |
| GET/POST | /api/v1/quotes | List / create |
| PATCH | /api/v1/quotes/:id | Update lines — prices merge on text-only edits |
| POST | /api/v1/quotes/:id/send | Send quote |
| GET/POST | /api/v1/invoices | List / create |
| PATCH | /api/v1/invoices/:id | Update draft / allowed actions on GET |
| POST | /api/v1/invoices/:id/revise | Revise issued invoice in place |
| POST | /api/v1/invoices/:id/email | Email invoice |
| GET/POST | /api/v1/visits | Schedule visits |
| GET | /api/v1/timesheets | Time entries / payroll periods |
| GET/POST | /api/v1/receipts | Receipts + job cost link |
| POST | /api/v1/properties | Create site with clientId in body |
| GET | /api/v1/search | Global search |
| POST | /api/v1/batch | Batch operations |
Machine discovery
Human docs
Scopes
Request only what you need (OAuth and API keys).
| Scope | Description |
|---|---|
| forge:read | View jobs, clients, quotes, invoices |
| forge:jobs:write | Create and update jobs |
| forge:quotes:write | Create, update, and send quotes |
| forge:invoices:write | Create and manage invoices |
| forge:clients:write | Create and update clients |
| forge:receipts:write | Upload and manage receipts |
| forge:team:read | View schedule and time entries |
| forge:team:write | Assign crew and manage timesheets |
| forge:admin | Full workspace access |
Support
Integration questions: [email protected]
Status check: /api/v1/health