# DAWKA living documents

Create a document and its private URL is emailed to you. Then edit it in a browser, or
give the URL to an AI agent, which edits it by POSTing JSON. No account is needed. The URL
is the key, so keep it private.

## Create

    curl -X POST https://dawka.ai/d -H 'content-type: application/json' -d '{"email":"you@example.com","templateId":"competitive-landscape"}'

Body fields:
- email (required): where the document's link is sent. The link is not returned in the response.
- templateId: one of blank, competitive-landscape, black-friday-vacuum, proud-to-take-job-search, tokyo-trip, spanish-by-june, side-project-before-winter, twelve-pieces-worth-reading, next-ten-customers, product-requirements-document, product-roadmap, opportunity-brief, ux-research-plan, user-journey-map, accessibility-evaluation, architecture-decision-record, threat-model, incident-response-plan, incident-postmortem, service-runbook, release-rollout, ideal-customer-profile-positioning, marketing-strategy, campaign-brief, editorial-calendar, sales-playbook, sales-discovery-guide, customer-onboarding, customer-success-plan, quarterly-business-review, troubleshooting-knowledge-base, client-intake-kickoff, crisis-communication, annual-operating-plan, annual-budget-scenarios, rolling-cashflow, budget-versus-actual, standard-operating-procedure, enterprise-risk-register, business-continuity-plan, procurement-decision, board-agenda-minutes, employee-handbook, job-description-scorecard, interview-rubric, performance-review-goals, new-hire-onboarding, healthcare-admin-handoff, lesson-study, education-research-analysis, manufacturing-process-improvement, construction-rfi, rental-inspection-repair, hotel-front-office-handover, destination-readiness, fleet-inspection-repair, crop-season-harvest, environmental-management, public-service-continuity
- title, summary
- includeExamples (boolean, default false): copy fictional example content with visible example labels.
- sections: build your own structure instead of a template, e.g.
  [{"title":"Goal","criteria":["Measurable"],"content":"..."},{"key":"risks","title":"Risks","blockKind":"checklist"}]

The response is 202 {"sent": true}. Once the person has the link, GET <link>/help for
instructions tailored to that document, including its section keys.

## Operations

POST a JSON body to the document URL. Either one op:

    {"op": "section.update", "section": "<key>", "content": "markdown"}

or a batch, applied atomically (all succeed or none do):

    {"baseVersion": 7, "ops": [ {...}, {...} ]}

"baseVersion" is optional. When you send it and someone else changed the document
since you read it, the response is 409 with the current state. Re-read, then retry.
Every successful response returns {"version", "state"}.

| op | fields |
|---|---|
| document.update | title?, summary? |
| charter.update | identity?, goals?, audience?, autonomy?, cadence?, budget?, model? |
| section.update | section (key), title?, purpose?, criteria? (string[]), instructions?, blockKind?, layout?, autonomy?, tools?, mdx? or content? (markdown) or blocks?, citations? |
| section.add | title, key?, purpose?, criteria?, instructions?, blockKind?, layout?, autonomy?, tools?, mdx? or content? or blocks?, after? (key, or null for first) |
| section.remove | section |
| section.move | section, after (key or null) or position (0-based) |
| note.add | section, body |
| note.remove | noteId |
| source.add | url or text, title?, section?, note? (what the source is for) |
| source.update | sourceId, title?, url? or text? (matching its kind), section? (key, or null for the whole document), note? (null clears) |
| source.remove | sourceId |
| input.add | section, kind ("url", "search", or "section"), target, cadence? |
| input.update | inputId, cadence |
| input.remove | inputId |

"layout" places a section on the page: {"width": "full" | "two-thirds" | "half" | "third", "variant": "plain" | "card" | "callout"}.
Sections flow left to right and wrap, so two "half" sections sit side by side. Send only the fields you change.

The charter (state.charter) is what the document is for: identity (who it is and its voice),
goals (what it keeps true), audience, autonomy ("manual", "propose", or "apply": Manual, Review first, or Automatic), cadence ("manual" | "daily" | "weekly" | "monthly"),
budget ({"monthlyUsd", "perRunUsd"}, soft spend limits in US dollars) and model (an OpenRouter
model id, or null). Send only the fields you change. A section's "autonomy" overrides the
charter for that section; null inherits it. Manual sections are excluded from the built-in agent;
Review first produces feedback and proposed edits, and Automatic may update content. Changes to
structure, criteria, instructions, and permissions always require owner review. Your own edits
through this capability API remain immediate and have no DAWKA fee.

The built-in agent runs only for the signed-in owner and uses that owner's OpenRouter key.
OpenRouter bills the owner directly. DAWKA does not sell credits or add model, operation,
or search fees. Missing or rejected keys must be fixed from the owner's /app dashboard.

Inputs are the changing information a section depends on: a public "url" or a "search" query,
checked on a cadence ("daily" | "weekly" | "monthly", default "weekly"), or another "section"
(by key; no cadence, and no cycles). "tools" are what the section's agent may call while
writing: {"fetchDomains": ["example.com"], "search": true}. Both are partial and appear in
state.sections[].inputs and .tools. When you maintain a section, read its inputs first and
stay within its tools.

Sources and their read previews are private to people holding the edit link and are not
included in public share links. The browser previews local files before upload and sends
only text the editor explicitly saves.

A document with an owner also has its own agent, which reads the charter and maintains the
document on its cadence after the owner explicitly starts it. New documents are paused,
and accepting a generated draft does not start ongoing maintenance. Its changes appear in state.activity with actor "agent". Only the
owner, signed in on dawka.ai, can run it or accept what it proposes; you work alongside it.

Setting "criteria" replaces the whole list. Send only one of "mdx", "content", or "blocks"; it replaces the
section's content and keeps the previous version in its history (last 20).
Citations are objects like {"title": "...", "url": "https://..."} or {"title": "...", "sourceId": "src_..."}.

Shorthand: POST /d/<token>/sections/<key> with the section.update fields, e.g. {"content": "..."}.

Block formats for "blocks" (use instead of "content" when the section's blockKind is not rich_text; item ids are optional):
- rich_text: {"kind":"rich_text","markdown":"..."}
- checklist: {"kind":"checklist","items":[{"text":"...","checked":false}]}
- table:     {"kind":"table","columns":[{"key":"name","label":"Name"}],"rows":[{"name":"..."}]}
- timeline:  {"kind":"timeline","items":[{"date":"2026-10-01","title":"...","detail":"..."}]}
- metrics:   {"kind":"metrics","items":[{"label":"...","value":"...","trend":"up"}]}   (trend: up | down | flat | null)
- sources:   {"kind":"sources","citationIds":["..."]}

Restricted MDX format (use instead of "content" or "blocks"):

    mdx: {"source":"# Results\n\n<Chart dataKey=\"trend\" />","data":{"trend":[{"label":"Q1","value":12}]}}

MDX accepts the document's allowlisted presentation components and inert JSON data addressed by dataKey.

Limits: 50 sections, 30 criteria per section, 100000 characters of content per section, 50 sources, 10 inputs per section, 100 ops per request.
