# FieldOps Cloud API Contracts

Date: 2026-06-16

## Gate 22 Scope

Gate 22 makes the current API surface truthful and machine-verifiable. It does not launch a general public REST API.

## Active JSON Contracts

All active JSON endpoints return:

- Success: `{ "success": true, "data": {}, "meta": {} }`
- Error: `{ "success": false, "error": { "code": "...", "message": "...", "fields": {} } }`

The application boundary also returns JSON envelopes for unknown or forbidden `/api/*` routes:

- Unknown API route: HTTP 404, `api_route_not_found`
- Forbidden API route: HTTP 403, `api_forbidden`

| Route | Contract |
| --- | --- |
| `POST /ai-assistant/generate` | Logged-in tenant user with `use_ai_assistant`; web-form CSRF required; deterministic local assistant only; No external LLM is called. |
| `POST /api/offline-sync` | Logged-in tenant user with `update_jobs`; accepts bounded offline queue payloads; validates visible/assigned jobs; writes `offline_sync` audit entries; returns accepted/rejected rows and counts. |
| `POST /api/billing/stripe/webhook` | Provider signature required; remains disabled until Stripe secret, webhook signing secret, and price mapping are configured; not a live payment gateway until owner credentials and approval are supplied. |

## Signed Form API-Style Contracts

These routes live under `/api/*` because they intentionally bypass normal session CSRF and instead use signed customer portal tokens. They are browser form endpoints and may return redirects or portal HTML validation errors.

| Route | Contract |
| --- | --- |
| `POST /api/portal/quote` | Signed portal token for a quote; accepts approve/decline; persists quote status and accepted billing schedule where configured; redirects back to the portal. |
| `POST /api/portal/invoice-payment` | Signed portal token for an invoice; records sandbox/manual payment only; validates amount and payer email; redirects or re-renders portal validation errors. |
| `POST /api/portal/booking-request` | Signed portal token for a job, quote, or invoice; validates requested appointment details; persists a customer-requested appointment when schedule storage is configured. |

## Planned Public REST API

The routes below are planned only and are not live. They must not be documented, marketed, or tested as available until token auth, RBAC, tenant isolation, rate limiting, audit logging, pagination, and error handling are implemented:

- `POST /api/auth/token`
- `POST /api/auth/revoke`
- `GET|POST /api/clients`, `GET|PATCH|DELETE /api/clients/{id}`
- `GET|POST /api/jobs`, `GET|PATCH|DELETE /api/jobs/{id}`
- `GET|POST /api/quotes`, `GET|PATCH|DELETE /api/quotes/{id}`
- `GET|POST /api/invoices`, `GET|PATCH|DELETE /api/invoices/{id}`
- `GET /api/dashboard`
- `GET /api/reports/summary`
- `GET /api/team`

## Security Requirements Before Public API Release

- Token storage must use hashed tokens only.
- Tokens must be scoped by tenant, user, role, and permissions.
- Every tenant-owned read/write must enforce tenant ownership server-side.
- API writes must be audited where they mutate customer, job, quote, invoice, payment, billing, or integration state.
- API errors must not expose secrets, SQL, raw provider signatures, or sensitive payloads.
- Rate limiting and abuse controls are required before internet exposure.
- Live integration and payment API paths remain blocked until real credentials, encrypted secret storage, webhook validation, idempotency, and rollback/reconciliation tests are complete.

## Verification

Run:

```powershell
composer api-contract-harness
```

The harness writes `docs/API_CONTRACT_HARNESS_REPORT.md` and verifies:

- JSON response envelope shape.
- `/api/*` 404 and forbidden JSON errors.
- API POST CSRF boundary behavior.
- Billing webhook disabled JSON error when provider secrets are absent.
- Active API-style route registration.
- Planned REST route absence.
- API docs mention active routes and truth markers.
