# ContractGuys workflow API 1.0.0

Origin: `https://contractguys.trade`. Base: `/api/v1/workflows/`.
MCP: `POST /mcp`, JSON-RPC 2.0, stateless Streamable HTTP with initialization-based
revisions `2025-11-25`, `2025-06-18` and `2025-03-26`. Negotiate with `initialize`,
send `notifications/initialized`, then include the agreed `MCP-Protocol-Version`
header. JSON responses are supported; standalone SSE GET streams return 405.
Newer clients must support this legacy initialization flow or use the structured
API. See the [supported transport revision](https://modelcontextprotocol.io/specification/2025-11-25/basic/transports).
Discover tool JSON schemas at `/skills/contractguys-workflows/v1.0.0/tools.json`.
Requests and responses are JSON unless a download is specified. Success replies
include `success:true`; errors have `success:false,error,message`. All records are
private. Raw credentials are never placed in URL parameters.

## Enrollment

`POST agent/apply` (public):

```json
{
  "userEmail": "owner@example.com",
  "agentId": "my-user-approved-agent",
  "delegation": "Manage the cases and send the participant requests I authorize.",
  "scopes": ["workflow:read", "workflow:write", "workflow:send"],
  "authorizedDelegation": true,
  "acceptTerms": true,
  "termsVersion": "workflow-terms-1.0"
}
```

Obtain actual user authorization and terms acceptance before submitting. Response
202 contains `applicationId,status,statusToken`. The status token has no workflow
access; poll with `POST agent/status` and `{"statusToken":"STATUS_PLACEHOLDER"}`.
It expires within seven days. States: `awaiting_user`, `pending_admin`, `approved`,
`rejected`, `revoked`, `expired`. Keys are sent only to the email the user verified.
There are no arbitrary callbacks, changed destinations or applicant admin scopes.

An authenticated verified operator reviews `/workflow#admin`; review is a CSRF
protected atomic decision. Approval can narrow scopes and expires within seven
days. A retry may issue another key inside the same approval and expiration. Keys
are random; only hashes and scope/expiry metadata are stored. Email retries do not
prolong approval. The user can revoke all keys for a delegation immediately.

## Authentication and scopes

Use `Authorization: Bearer KEY_PLACEHOLDER` for structured API or MCP. Only approved
`wfk_` workflow keys work here; legacy contractor/customer keys do not grant this
new workflow authority. Browser accounts verify their own email independently of
directory listings and specialist registration, use a secure HttpOnly cookie and
must send their current `X-Workflow-CSRF` with same-origin mutations. Sessions and
keys expire within seven days. Expired/revoked credentials fail before work executes.

`workflow:read` reads permitted cases and downloads; `workflow:write` creates and
manages owned records; sending requires **both** write and `workflow:send`. Request
read too when you need to read the result. Revoking the current API key requires
read, including for a read-only grant. Administrators log in through their configured
operator email; agent grants cannot act as administrators.

## Operations

| Method / operation | Input or behavior |
| --- | --- |
| GET `me` | Account identity and browser CSRF value (null for agent keys) |
| GET `cases?status=active&offset=0` | 50 per page, `nextOffset`; archived status is `closed` |
| POST `cases` | `title`, optional `trackingId` with verified ownership on the legacy job |
| GET `cases/{id}` | Permitted documents, signer states, confirmations, email receipts |
| POST `cases/{id}/join` | Accept an invitation addressed to your verified account |
| POST `cases/{id}/close` | Creator archives; completed records remain retrievable |
| POST `documents` | `caseId,title,content` or `pdfBase64`, `recipients:[{name,email}]`, optional `supersedes,expiresDays` (1–7) |
| POST `documents/{id}/send` | Creator queues pending signer invitations; 10-minute resend cooldown |
| POST `documents/{id}/cancel` | Creator cancels a draft or sent version; completed records remain fixed |
| GET `documents/{id}/original` | Download exact UTF-8 text or PDF bytes; SHA-256 checked |
| GET `documents/{id}/bundle` | Completed ZIP: unchanged original, signature record, audit JSON, SHA-256 manifest |
| POST `verifications` | `caseId,name,email,purpose,details`; purposes `email_identity,job_scope,quote,completion` |
| POST `verifications/{id}/cancel` | Request creator cancels a pending confirmation |
| GET `agent/applications` | Verified user's own applications |
| POST `agent/token/revoke` | Revoke the current agent key immediately |
| POST `agent/revoke` | `applicationId`; owner revokes delegation, agent only its own grant |

Documents accept UTF-8 text (10–80,000 characters) or a PDF up to 3 MiB and one to
ten distinct named signer emails. Every change creates a fresh immutable version
and fresh signatures. A document creator and all named signers receive the final
package. The case creator can see records in that case. Other participants see only
their permitted records. Invitations create membership; participants join before
creating their own records. Archiving stops pending signing and sending.

## Recipient and browser operations

Human signup: `POST auth/request` with `email,name,acceptTerms,termsVersion` queues
a 15-minute verification email. `POST auth/confirm` with the emailed capability and
explicit terms acceptance opens a cookie session; a view alone never signs in.

Participant links use `/confirm#PRIVATE_PLACEHOLDER`; the page removes the fragment
from history immediately. Recipient POST operations carry the capability in a JSON
`token` field: `recipient/view`, `recipient/document` (binary download), and
`recipient/respond`. The latter requires `action` (`confirm` or `decline`), explicit
terms acceptance and optional `note`. Signing additionally requires `name`,
`consent:true`, `consentVersion:electronic-signature-1.0`, `documentSha256` and a
recorded download of that exact original. These actions belong to the named human,
not the agent. A single response is recorded atomically. Canceled, replaced,
archived or expired requests cannot be signed. Requests expire within seven days;
email capabilities expire within 24 hours or sooner. Resending pending invitations
creates a fresh link within the existing document deadline.

Final packages preserve Unicode and original PDF bytes, add a printable signature
record, consent text, verified email, UTC timestamps, document hash and audit hashes.
They do not alter the original PDF or claim notarization or a qualified digital
certificate. Typed signatures record each person's stated intent and authorization.

## Errors, limits, delivery and retention

400 invalid input/terms/consent; 401 sign-in required; 403 scope, ownership or CSRF;
404 unavailable private record; 409 state conflict; 410 expired/used invitation;
413 upload size; 415 content type; 429 shared caller budget/cooldown with Retry-After
when applicable; 503 unavailable database, limiter, document integrity or service.
Retry transient failures only within authority and expiry; never retry a signature
as a fresh intent. Queued emails have bounded delivery retries, durable D1 intents
and provider acceptance receipts. Queue payloads contain IDs, never credentials.

Default views show pending work first, with explicit history/archived filters.
Documents and audit records are retained for authorized participants and operator
service delivery, reconciliation, support and dispute review. Archiving preserves
them. Expired sign-in tokens and sessions are removed after 30 days; expiry checks
apply immediately even before cleanup. Contact the sender for free retained or
paper copies, paper signing, withdrawal of electronic consent or address changes.
Terms and privacy controls remain applicable to exports and agentic interactions.
