# DocJacket Platform API — extended reference for AI tools DocJacket provides a stateful real-estate transaction operations and intelligence API for applications serving transaction coordinators, real-estate agents, teams, brokerages, and technology partners. Base URL: https://api.docjacket.com Canonical specification: https://api.docjacket.com/openapi.json (also YAML at /openapi.yaml) Every operation as Markdown: https://api.docjacket.com/api-reference.md Integration sequences: https://api.docjacket.com/integration-guide.md This document explains the API's model. It is deliberately NOT an endpoint catalog — the OpenAPI specification is the canonical source of truth for paths, parameters, schemas, and error codes, and it is generated from the deployed routes, so it cannot drift. Read this for concepts; read the specification for the contract. ## What DocJacket is DocJacket is transaction-coordination software for residential real estate. A "transaction" (also called a deal or a jacket) is the record of one property changing hands: the property, the parties, the contract documents, the negotiated deadlines, and the work required to reach closing. The product's job is to turn an executed contract into a tracked, deadline-driven workflow, and to keep every party informed as that workflow progresses. The API exposes that same model. ## The stateful transaction model This is not a stateless document-processing API. State accumulates on the transaction, and most operations read or mutate that state. A transaction owns: - Identity — property address, transaction type (Sale, Purchase, Listing), and side (Buyer or Seller). A transaction has exactly one side; the counterparty is a contact. - Status — a per-organization vocabulary, not a fixed enum. Read the organization's own list from GET /api/v1/transaction-statuses before writing a status. Changing status via PATCH /api/v1/transactions/{id}/status runs the same cascade the web app runs, which may create tasks and shift dates. It is not a field assignment. - Key dates — the negotiated deadlines (closing, inspection, financing, appraisal, and so on). These are calendar dates, not timestamps. Types come from a controlled vocabulary such as ClosingDate, InspectionDeadline, FinancingDeadline. A key date type appears at most once per transaction; writing the same type again updates it rather than adding a second. - Tasks — the work items, optionally linked to a key date so they move when the deadline moves. - Documents — the files, each with a classified document type and an extraction state. - Contacts — people and companies linked to the transaction with a role. Roles match exactly on the role name; an unrecognized role token silently reaches nobody, so read the role vocabulary rather than inventing role names. - Communications — email and SMS, unified into one per-deal thread. Because state accumulates, order matters. Create or resolve the transaction first, then attach dates, tasks, documents, and contacts to it. ## Authentication types Three credential types. They are not interchangeable, and a credential presented on another's routes is rejected. 1. Organization API key, prefix `mcp_at_`. Acts within exactly one organization — the key IS the organization, so no organization identifier is passed on these routes. Created in the DocJacket app under Settings -> Advanced -> API Keys. The same key also connects AI assistants over MCP at https://mcp.docjacket.com/mcp. 2. OAuth 2.1 access token (a JWT). Reaches the same organization-scoped operations as an `mcp_at_` key, carrying the same `read` / `draft` / `actions` scopes, but issued by a user authorizing your application rather than pasted by hand. The organization is carried in the token's `org_id` claim, so — as with a key — no organization identifier is passed on these routes. Use it when one application acts for many users; see "OAuth integration". 3. Reseller/partner API key, prefix `rsk_`. A cross-tenant credential for white-label partners. Accepted only on `/api/v1/orgs/*`. Used to provision organizations and read their entitlements and activity summaries — never to read the deal data inside them. To act inside a provisioned organization, use an organization key or an OAuth token for that organization. Send any of them as `Authorization: Bearer `. ## Permission levels and scopes Organization credentials — both `mcp_at_` keys and OAuth access tokens — carry one or more scopes, and the same three apply to each. Every operation declares the scope it requires, in the specification and in GET /api/v1/catalog. - `read` — GET operations. - `draft` — low-risk writes, such as completing a task or saving a status summary. - `actions` — side-effecting writes: sending email or SMS, deleting, provisioning, sharing documents externally. A key missing the required scope receives 403 with `code: "insufficient_scope"`. The reliable way to discover what a specific key may do is GET /api/v1/catalog, which returns every operation with a `callable` boolean computed against that key. Prefer that over inferring capability from the key's name or from a previous response. ## Rate limits Per key, per minute, fixed window: - 300 reads (GET, HEAD) - 60 writes (POST, PUT, PATCH, DELETE) Exceeding a bucket returns 429 with `Retry-After: 60` and the standard error envelope (`code: "rate_limited"`). Wait for the window to reset rather than retrying immediately. Unauthenticated requests are limited per IP address. ## Error envelope Every 4xx and 5xx response uses one shape: { "error": { "code": "...", "message": "...", "fields": { } } } Branch on `error.code`, which is stable. Do not parse `error.message`; it is human-facing prose and may be reworded. `fields` appears on validation errors only. Codes: `unauthorized` (401), `insufficient_scope` (403), `not_found` (404), `conflict` (409), `validation_error` (422), `rate_limited` (429). Important: a resource that exists but belongs to a different organization returns 404, not 403. A 404 therefore does NOT prove an identifier is unused. ## Idempotency Side-effecting sends accept an `Idempotency-Key` request header (any unique string up to 200 characters; a UUID is ideal). The first request executes and its response is stored; an identical retry replays that stored response with an `Idempotency-Replayed: true` header rather than sending again. Reusing a key for a different operation returns 422. Support is per operation, not universal — the specification marks the operations that honor it with an `Idempotency-Key` header parameter. Use it on anything that sends an email or an SMS, where a retry after a timeout would otherwise double-send. ## Versioning and deprecation The API is additive by default. New fields and new operations may appear at any time, so clients must ignore unknown response fields and must not depend on property order. Changes that would break an existing client — removing or renaming a field, tightening a type, changing an error contract — ship only as a new major version at a new path (`/api/v2`). `/api/v1` is not broken in place. A deprecated version stays available for at least six months after its successor ships. ## Main API resource groups Meta, Transactions, Messaging, Key Dates, Tasks, Documents, Extractions, Contacts, Disclosure Packages, Proposals, Templates & Forms, Webhooks, Organization, and Organizations (Partner). The specification's tag list carries a description of each, and /api-reference.md lists every operation under its group. ## Recommended integration sequence 1. GET /api/v1/health — confirm the key works and read its scopes. 2. GET /api/v1/catalog — discover which operations this key may call. 3. GET /api/v1/transactions — list or search the existing book of business. 4. Upload a contract and extract it (see below). 5. Apply the extraction to create or enrich a transaction. 6. Add key dates and tasks. 7. Subscribe to webhooks so you are pushed changes instead of polling. 8. GET /api/v1/usage — monitor call volume and error rate. The full sequence with concrete endpoints is at https://api.docjacket.com/integration-guide.md. ## Document-to-transaction extraction DocJacket's core intelligence feature reads an executed contract and proposes the structured deal: parties, price, and the negotiated deadlines. The flow is asynchronous: 1. POST /api/v1/documents/upload-url — get a presigned PUT URL, then upload the PDF directly to it. (POST /api/v1/documents accepts a base64 body instead, for small files.) 2. POST /api/v1/extractions — start the job from the completed upload. 3. GET /api/v1/extractions/{jobId} — poll for state and results, or subscribe to the `extraction.completed` webhook and skip polling. 4. Review the results. Extraction is a proposal, not a commit — fields carry confidence and citations back to the source document, and low-confidence or conflicting fields are surfaced as warnings for a human to resolve. 5. POST /api/v1/transactions — apply the extraction. Without a transaction identifier this creates a new transaction; with one it enriches the existing transaction. Treat extraction output as requiring review before it drives an irreversible action. Do not auto-send client communication off an unreviewed extraction. ## Webhooks Register a subscription with POST /api/v1/webhooks, listing the event types you want (or `"*"` for all). Read the available types from GET /api/v1/webhook-events; the OpenAPI document also describes each one, with its payload, under `webhooks`. Each delivery is a POST carrying: - `X-Webhook-Signature` — `sha256=`, HMAC-SHA256 over the raw request body using your subscription's signing secret. Verify over the bytes as received, before parsing, and compare in constant time. - `X-Webhook-Event-Type`, `X-Webhook-Event-Id`, `X-Webhook-Timestamp`. Deduplicate on `X-Webhook-Event-Id`: retries reuse it. Respond 2xx promptly; repeated failures open a circuit breaker on the subscription. Rotate the secret with POST /api/v1/webhooks/{id}/regenerate-secret and send a sample with POST /api/v1/webhooks/{id}/test. ## Partner / OEM integration concepts White-label partners embed DocJacket under their own brand and provision organizations for their own customers. - A reseller key (`rsk_`) provisions and administers organizations. It is a control plane credential: create an organization, add and remove seats, read entitlements and activity summaries. - It is NOT a data plane credential. It cannot read the transactions, documents, or communications inside a provisioned organization. That requires an organization key issued for that specific organization. - Each provisioned organization is a separate tenant. Its data is reachable only with its own credential. ## Tenant isolation — required behavior for AI agents Do not infer, assert, or attempt access across organizations. - A credential grants access to exactly one organization (or, for a partner key, to the provisioning surface of the organizations it owns). - Identifiers are not capabilities. Holding a transaction, contact, or document identifier does not imply access to it; an identifier belonging to another organization returns 404. - A 404 means "not available to this credential". It does not mean the record does not exist, and it must not be used to probe for existence. - Never combine data retrieved with one organization's credential with another's, and never present one organization's data in another's context. ## What this API does not do - It does not send email from a DocJacket address on your behalf for deal communication; deal email routes through the acting user's connected mailbox. - It does not expose other tenants' data under any credential. - It does not guarantee extraction accuracy without review.