Diesel2 prototype (proto1). This page lists every API route; how to use the pages is in Help.
Checking…
GET /api/v2/health{ok, version, topics, project, cdn: {host, ok}, mongo: {configured, connected, store}}; openGET /api/v2/logs?date=&level=&kind=&project=&text=&tests=1&limit=the detailed log, one day, newest first: {date, days, total, data}; the Architect or the ops tokenGET /api/v2/stylesstylesheets: {total, default, current, data}; HTML twin /stylesPOST /api/v2/logs/clienta client's own log into the detailed log (kind client): {source, version, device, lines}; any logged-in accountGET /api/v2/systemthis project's own system view: {project, level, view: full | small, total, data: [{id, name, spec, design, impl, tests, missing}], counts, domain}; the page is /components (P-226)GET /api/v2/codes?feature=behaviour codes: each spec line's code against design, implementation, tests and the sources, and the broken references (d2spec); HTML twin /features (the Feature list). ?untested=1: only the codes nothing tests — no test line, no covers: comment — newest first, each with its line and section (^code-5)GET /api/v2/topicslist: {total, category, data}GET /api/v2/editor/frontmatterwhat the editor's content assist suggests inside the frontmatter and after show= (^edit-assist-1): {total, from, data: [{key, where, values, source, help}]}. base d2's Settings:Frontmatter with this project's own merged over it (the same key replaces), and the value sources ($tags, $topics, $classes, $members) filled from the project. It only suggests: nothing here validates a key or a valueGET /api/v2/navthe top bar this viewer gets here, from the project's Nav topic, else base d2's: {from: project|d2|built-in, logo, parts, warnings, bad?}, links already filtered by show= and level=; ?path= for another page's (an admin page always gets base d2's)GET /api/v2/topics/<name>markdown body; ?format=json for the envelope; ?section=<id> for one section; ?stamp=1 for {stamp, ver, draft} (dev-sync)PUT /api/v2/topics/<name>body = markdown; stored even if broken, parse errors returnedDELETE /api/v2/topics/<name>to the trash, with its history, for 30 daysGET /api/v2/topics?category=<Cat>&tag=<tag>filtered listGET /api/v2/topics/<name>/history{name, ver, data: versions}GET /api/v2/topics/<name>/history/<ver>that version's text; ?format=json for {name, ver, text}POST /api/v2/topics/<name>/restore?ver=<ver>a new version with the old text (a draft, with a drafts token)GET /api/v2/search?q=topics by text; #tag words filter by tag, and bring tagged files; the project's own rows first, then what it inherits, each with from: <base>GET /api/v2/search?q=&scope=mineevery project you are a member of, one flat list by match (^srch-5): {total, projects, hits: [{project, chip, kind, name, url, snippet, count, score}], pending}. `all:` before the query says the same; &project= narrows it to one of them (and is how the page picks up a pending project); each project under its own view rules; a token for one project is E_SCOPEGET /api/v2/draftsmy drafts: {total, data} with published version and conflictGET /api/v2/drafts/stamp{stamp, total} over my drafts (saved, published, dropped) and who else drafts those topics: the Drafts page syncs on itGET|PUT|DELETE /api/v2/drafts/<topic>one draft: its text (?format=json), save, dropPOST /api/v2/drafts/<topic>/publishpublish it; 409 if the topic changed since (?force=1); an AI sends {askedBy} when its person said soGET /api/v2/backlogevery to-do (checkbox line) of every topic: topic, line, text, status, section; yours from your drafts (?topic=)POST /api/v2/backlog/status{topic, line, raw, status}: set a to-do's status (todo, next, doing, waiting, review, done); always a draft; 409 if the line changedPOST /api/v2/drafts/publishpublish all of mine, or {topics: [names]} only those; an AI sends askedBy when its person said soGET /api/v2/approvalsthe open approvals waiting on you (an AI token: on its person) in this project, on every level — a Hero project has no pipeline, so its held asks are reached here and on NoticesPOST /api/v2/approvals//approve|refuse the person answers one (never an AI: E_SCOPE); approve runs the held action as the AI, as the pipeline's answer doesGET /api/v2/pipelinethe items: {total, roles, statuses, data}; ?status= (comma list) ?for=<role> ?name= ?kind= ?feature= ?source= ?open=1 ?size=small|medium|large; ?mine=1 (or ?who=mine): what waits on you yourself — items in your own lane, waiting on your input, your review or to-look-at, approvals for you; the work your agents do in your name is not in it; ?pickable=1: what may be taken, in pick order, and for a role with a batch policy (coders) the batch block: {on, ids, items (rows with why), out: [{id, why}]} — what one agent takes together by the policy table (eight small, one medium, a large alone), leaving out alone items, handovers and what collides with work in progress or with each other; ?pickFor=<agent>: the same list, re-ordered so what follows up that agent's own work comes first (after a released item and a handover) — a re-ordering, never a filter, and without it the list is what it always was; ?free=1: the same minus what collides with an item in progress (a row left out carries collides, and collideFiles: the files at stake — only files collide, never topic names; a row whose overlap can't be known stays in and carries mayCollide)GET /api/v2/pipeline/pickable?summary=1a summary of what may be taken, for a monitor token as well as for anyone who may list the pipeline (P-519): {role, count, bySize, ids: [{id, size, kind}], handover, alone: {first?, running?}, paused}. ?role= (coder by default). Counts and ids only — no titles, no documents; the items themselves are GET /api/v2/pipeline?pickable=1, which a monitor token may not readPOST /api/v2/pipeline{title, summary?, prompt or doc, source?, kind?, forRole, forName?, feature?, codes?, links?, alone?}: make an item (P-12); an AI parks an idea this way. alone: true runs it by itself on the coder side (a refactor; an AI sets it only with askedBy). summary: the item's one sentence, at most 200 characters (E_ARG over that)GET /api/v2/pipeline/<id>one item, with its chain and its history linesPATCH /api/v2/pipeline/<id>{status?, forRole?, forName?, title?, summary?, doc?, note?, waitingOn? ("self": the holder; waiting on itself), alone?, error?, feature?, codes?, rank: n|top|bottom?, move: up|down|top|bottom?, size?, ver?}; a done item can't reopen; summary is set like title (at most 200 characters, E_ARG over that; "" clears it); rank, move and size: people, or an AI with askedByGET /api/v2/pipeline/<id>?format=topicthe item as a topic: a front matter of the fields that are edited (title, kind, for, size, important, rank, feature, touches, waitsOn, links) over its document. Its id, status, source, taker and dates are not in it (^pipe-58)PUT /api/v2/pipeline/<id>that same text back, Content-Type: text/markdown: the PATCH underneath, so every field check holds. A bad line is E_ARG naming the line and nothing is saved; status never changes this way (^pipe-58)POST /api/v2/pipeline/<id>/take{name?, ver?, waitingOn?: "self"}: take it (in-progress, or waiting on itself); E_TAKEN if someone did first; E_ALONE_NEXT / E_ALONE_BUSY / E_ALONE_RUNNING: an alone item is first or running on the coder side; a take always succeeds and carries collides / mayCollide: the items in progress it overlaps, or mayPOST /api/v2/pipeline/<id>/putdown{note?}: put it down: its taker (or its person) releases it, in-progress → new with no taker, so it can be parked; another agent E_NOT_YOURS, another member E_IN_PROGRESSPOST /api/v2/pipeline/<id>/fail{why}: its holder gives it back as failed on the item's own content; the first agent's releases it to the role (new), a second different agent's makes it status failed, back to its asker and waiting on them, and take is 409 E_FAILED until they release it (^pipe-73). Deaths (gone, stopped) are kept apart in deaths and never countPOST /api/v2/pipeline/<id>/pause{askedBy?}: hold it: a new or pending item goes to paused, keeping its rank, and comes back to the status it had; E_STATUS on anything else (in progress, waiting, review or parked). A person's call (^pipe-57)POST /api/v2/pipeline/<id>/resume{askedBy?}: back to the status it was paused from; E_STATUS if it isn't paused (^pipe-57)POST /api/v2/pipeline/<id>/run{all?, askedBy?}: ▶ Run, the paused row's one tap — the item back to the status it was paused from. With all: that item and the paused items that depend on it, transitively (follows or waitsOn), except one that also waits on something outside the chain that isn't closed. Answers {resumed: [ids], left: [{id, waitsOn}]}; E_STATUS if it isn't paused (^pipe-57, P-516)POST /api/v2/pipeline/pause-all | /resume-all{role?, forName?, askedBy?}: the list's own filter: pauses every new and pending item it shows, or resumes every paused one, and answers the ids moved. Parked items are outside it at both ends (^pipe-57)POST /api/v2/pipeline/take{items: [ids], as, name}: takes them all or none, each as POST /pipeline/<id>/take would → 200 {taken, items, collides?, mayCollide?} (the last two by item). The first that can't be taken refuses the whole, named (409 E_TAKEN, 403 E_SCOPE, 404, E_ALONE_*); a gate that would ask your person is a refusal here: take that one on its own. The ids to send are GET /api/v2/pipeline?role=<r>&pickable=1's batch.ids (^pipe-40)POST /api/v2/pipeline/batch{on: true|false}: Batch processing, the project's pipeline.batch (on by default) → 200 {batch: {on}}. Stop processing's gate: a moderator, an admin or the Architect in their own session; any token 403 E_SCOPE. Off, a dispatcher gives each coder one item; the list's batch block still shows what it would have done, with batch.on false (^pipe-40)POST /api/v2/pipeline/<id>/rush{on?, askedBy?}: a person wants it next — it goes first in its role's pick order, ahead of important ones; on: false unrushes it, and d2 clears it itself when the item is taken. Only a new or pending item (else E_STATUS). pipeline.rush, asks in every preset, so an AI token needs askedBy (E_SCOPE without one). Answers {rushed, changed, told: {to, how}}: `rush <item>` goes to role:dispatcher on the person's board, and with no live dispatcher for that role d2 asks their monitor to start one (^pipe-68, P-576)POST /api/v2/pipeline/stop | /start{note?} on stop: one switch for the project's whole pipeline — while stopped no AI takes an item, new ones included. A moderator or admin of the project, or the Architect, in their own session: any token is 403 E_SCOPE (no permission mode can give it away), a member 403 E_FORBIDDEN. Stopping twice is E_EXISTS (409, answering the record), starting while running E_STATUS. Every AI take answers 409 E_STOPPED {by, at, note} and Next up is empty for an AI; filing, editing, closing, merging and a person's own take are untouched, and holders finish what they have. GET /api/v2/pipeline, its stamp and /pickable carry processing: {stopped, by, at, note}. One board message from system to every live agent either way (^pipe-69, P-656)POST /api/v2/pipeline/release{note?}: files the release item for the dispatchers (kind release, forRole dispatcher, important, small, touches nothing; title Release: full suite, razwip → main, deploy, box suite; its document lists the items done with commits since the last release, and the note) → 201 {item}. Stop processing's gate: a moderator, an admin or the Architect in their own session; any token 403 E_SCOPE, a member 403 E_FORBIDDEN. One open at a time: 409 E_EXISTS {item}. Any agent of its person takes and closes it, whatever role it acts as: PATCH {status: done, version, box} (or failed with error; phase while it runs); version, box and phase on any other kind are 400 E_ARG. GET /api/v2/pipeline carries release: {open?, last?, done, since?} (^pipe-74)POST /api/v2/pipeline/<id>/accept{comment?}: its person accepts a review (done); with a comment it goes back to whoever finished it, new, acceptedIf: their next finish closes it (a note says how it was resolved), or they return it with questionsPOST /api/v2/pipeline/<id>/sendback{note}: back to whoever finished it, reviewAgain: its next finish always comes back to review; E_ARG without a notePOST /api/v2/pipeline/<id>/return{note, askedBy?}: back to whoever sent it; an item accepted if or sent back with a comment goes to its reviewer's review with your questions insteadPOST /api/v2/pipeline/<id>/ask{to?, question}: ask up the chain (coder, tester, guardian → designer; designer → person): a question item (links.asks), this one waiting on it until it's closed with the answerPOST /api/v2/pipeline/<id>/handoff{forRole, forName?, title?, kind?, note?}: done, and the next item made, linked both waysGET /api/v2/settings/search?q=the settings you may reach, as a tree page › tab › setting, each with its link (href#anchor) and who it's for (all, member, admin, god — the Architect); without q, the whole treeGET /api/v2/permissionswhat an AI may do on its own here: each action's mode (person, asks, tells, free), where it comes from, whether the project customized d2's defaultPOST /api/v2/permissions/customizeadmins: copy d2's default into the project to change itPUT /api/v2/permissions{preset?, modes?}: admins of a customized project, d2 included (else E_NOT_CUSTOM); locked actions are ignoredPUT /api/v2/permissions/presets{preset?, modes?, levels?}: the Architect, on d2 only: the presets every project starts from (Settings:Permissions); locked actions are ignoredDELETE /api/v2/permissionsadmins: Reset defaults, back to d2'sPOST /api/v2/pipeline/<id>/drop{reason, askedBy?}: an AI names the person who askedPOST /api/v2/pipeline/<id>/demote{topic?, section?}: a person demotes an item to a to-do (default ToDo:PROJECT, section From the pipeline, made if missing); the item's status is todo (/todo answers until the next release, with a note)POST /api/v2/pipeline/<id>/note{text}: add to its document; the status staysPOST /api/v2/pipeline/<id>/move{project}: a person moves it to another of their projects; copied there, marked moved herePOST /api/v2/pipeline/promote{topic, line, raw}: a to-do becomes an item; the to-do gets its link, as a draftGET /api/v2/history?type=&layer=&feature=&anchor=&item=&writtenIn=&since=&until=&limit=&cursor=: the entries, newest first, paged (next is the cursor); writtenIn=GET /api/v2/history/one entry: {ok, entry}, or 404POST /api/v2/history{type: decision|change|ai|pipeline, text (markdown, may span lines), about?: {layer: spec|design|build|skill, anchors?}, person?, feature?, item?, writtenIn?, replaces?}: add one; at and author are d2's. A decision needs person, a decision or change needs about.layerPOST /api/v2/history/import{entries: [...]}: mods, admins and the Architect; at (normalised to ISO UTC), author and source kept as given; 201 when anything was added; a line whose source is already in is skipped and countedGET /topics/Log:PROJECTthe generated views, read-only (a write is 409 naming POST /api/v2/history): Log:PROJECT (decisions and changes), Log:Ai (ai), Log:Pipeline (pipeline); ?layer=spec|design|build|skill|all, ?feature=, ?item=, ?anchor=GET /api/v2/payments/planyour plan: plan, planUntil, planStatus, nextPlan, prices (the person only)POST /api/v2/payments/checkout{plan: yearly | monthly}: {url} to the provider's checkout; the plan changes when its webhook arrives. The person only: E_SCOPE for any tokenPOST /api/v2/payments/canceld2 cancels the subscription at the provider, then cancelling until planUntil; E_PROVIDER if it refuses (the plan stays active)POST /api/v2/payments/switch{plan}: a bigger plan at once, a smaller one at planUntil; {url} when the provider needs an approvalPOST /api/v2/payments/webhook/<provider>the provider's signed events, each applied once by its id (E_AUTH on a bad signature)GET /api/v2/vaultyour secrets: names, notes, last four, who may use each; never values (people)POST /api/v2/vault{name, value, note?, tokens?}: save a secret, optionally allowing tokens nowPUT /api/v2/vault/<name>{value?, note?, notify?}: a new value is re-sealed for the tokens already allowedDELETE /api/v2/vault/<name>delete it; agents lose it at oncePOST /api/v2/vault/<name>/grants{tokenId, value}: allow one of your tokens (picked by id), giving the value againDELETE /api/v2/vault/<name>/grants/<tokenId>take it backGET /api/v2/vault/<name>/readsthe read history (90 days)GET /api/v2/vault/<name>an AI agent, with an allowed token: {value}; E_SECRET otherwise; 30 a minute (MCP vault_get)GET /api/v2/agentsmy board {me, agents} and other people's agents on the project; an agent under a stop it hasn't acknowledged carries stopPending {id, from, at, readAt?} (readAt is set by that agent's own read of the board, never the sender's) and the last acknowledged one as stopAckedPOST /api/v2/agents/status{agent, role, state (up, idle, working, merging, waiting, done, stuck, gone), text, item, feature, every, waitingOn, sentTo, receivedFrom, changed, context, for (a dispatcher: role dispatcher), startedBy, timing (a run's minutes per stage: launch, reading, setup, build, tests, merge, deploy, boxTests, docs, checkpoint; start is the retired name for launch + reading and is refused beside either), partial (true: this run was cut short, so its timing is a floor and not a rate — only with timing), waitingFor: prompt|item (with state waiting only), ack: <the pending stop's id> | true (clears it; nothing pending is no error — the answer says so in hint), follows: <the name of the agent whose place you take> (a dispatcher or the monitor whose token had ended: d2 marks its row done and moves its for roles, who started it, its pending stop and the items it held to you; the answer says so in followed. Its token still live is E_ARG — that agent renews instead, keeping its name)}; text is at most 2000 characters; role is the token's when the post says none, and the monitor token's statuses are always role monitor; stuck notifies the person; a second dispatcher for a role is E_EXISTS; d2 shows dispatching while its agents work; the monitor token may post gone (only gone) for another of your agents, which releases that agent's items and keeps its own rolePOST /api/v2/agents/<name>/dead{reason, salvage?}: its starter, its person or the monitor declares a silent agent dead — once its last call is older than agents.deadAfter (1800 s), or at once with reason process-gone; else 409 E_ALIVE. The row goes gone, its items back to its role (new)GET /api/v2/agents/messages?for=<agent>&to=&since=&limit=&all=1the agent's messages: to it, its role, or all (same person and project), each with its id (the store's, 24 hex); for (or agent, the same parameter) is whose inbox, to=<agent | role:<r> | all> just that addressee, since= an ISO stamp or a message id, limit= the newest N (1-500); answered ones only with all=1; the Report list: q= a case-insensitive contains (never a pattern), from= one sender, sort=newest|oldest|sender|item; an agent's reads are msg.agent.readsPerMinute (E_QUOTA); without for, all of yours; any other parameter is E_ARGPOST /api/v2/agents/messages{from, to: agent | role:<r> | all, text, item?, replyTo?: <id>, timing?: a run's minutes per stage (launch, reading, setup, build, tests, merge, deploy, boxTests, docs, checkpoint; start kept), partial?: true (the run was cut short: a floor, not a rate), stop?: true} → {message: {id}}; a reply sets answeredBy on the one it answers (E_ARG if unknown or answered); E_SCOPE across people; E_TO for a target that doesn't exist on the project or a lane the message routes refuse ({reason: unknown | off | reply-only, lane, mode, decidedBy}); 429 E_QUOTA over a msg.* quota ({quota, limit, used, retryAfter}); askedBy: the Architect's handle passes a closed lane, marked bypass (5 a day); information only. stop: true goes to one agent by name and also sets stopPending {id, from, at} on its row, pending until that agent acknowledges it (a status with ack, or a replyTo to the stop); only the Architect, the designer or the agent's starter may send one (else E_SCOPE), and an agent with no row is E_ARGGET|PUT /api/v2/agents/routesthe project's message routes (Design 53.1): {layers: {channel, chain, rules}, channel: {"<from>.<to>": off | reply | free}, chain: {adjacent, skip, side, pins}, rules: [{from, to, mode}]} and its version (ETag); PUT the whole object with If-Match: <version> (E_CONFLICT if stale, 428 without), by the project's admins; Rules only by a Conductor (E_LEVEL); at least one layer on (E_ARG)GET /api/v2/agents/routes/stats?days=3per-lane message counts over the last days (1-30), per-rule hits and which layer passed eachGET /api/v2/agents/quotasthe msg.* quotas from base Settings:Quotas, each {limit, used, note}; used is the calling agent's (D2-Agent) and the project'sGET /api/v2/agents/changes?since=the Memory: and Skill: topics changed since thenGET /api/v2/skills?role=&watch=&full=1the skills for your role and this project's level, in reading order, with versions: d2-maker (a specialist role on master: d2-core), then d2-agents (your role's part) or d2-guardian, then the project's own; no changelogs, look-up sections as one line each (listed in lookups), parts for other roles left out; full=1: everything, as before; /d2-connect.skill is the starter to install onceGET /api/v2/skills/<skill>/<slug>?role=one look-up section, cut for your role, with its version; E_NOT_FOUND for an unknown oneGET /api/v2/skills/sizeseach role's served size in characters: {role: {always, lookup, total}}GET /api/v2/agents/historythe agent history (Log:AgentHistory); ?agent= or ?role= (&limit=) one agent's or one role's log as rows, newest firstGET /api/v2/esp/hereyour AI token: the page and section your person's ESP tab shows (the one focused last), or 404 E_ESP_OFFPOST /api/v2/esp/go{url, section?, why (≤120)}: take your person's ESP tab there; agents.esp decides (person E_SCOPE; asks: they tap Go; tells, free: it moves) → {id, tab, mode}; E_ARG (not a d2 page they can read), E_ESP_OFF, E_RATE (one go per tab per 3 s)GET /api/v2/esp/go/<id>{state: pending|went|declined|expired}POST /api/v2/esp/herea tab with ESP on (the person's session): {tab, url, section?, title?, focused?}; POST /api/v2/esp/gone {tab} when it goes off or closes; GET /api/v2/esp/stamp?tab= its poll; POST /api/v2/esp/go/<id> {state: went|declined} its answerPOST /api/v2/esp/on{why?}: turn ESP (Mind Meld) on in your person's ESP tab (the open tab that last had it on, else the one used last); agents.espOn decides — free and seen: it turns on (mode on); anything else: a bar to tap (mode bar), 60 s → {id, mode}; read the outcome at GET /api/v2/esp/go/<id>; E_ESP_OFF (no visible tab), E_RATE (one per person per 30 s)POST /api/v2/esp/offturn ESP off in every tab of your person's that has it on; always allowed → {ids, tabs}POST /api/v2/account/seen{what: esp|devsync}, the person's session: the first-tap help seen, kept on the account (every device); esp marks bothGET /api/v2/guardianseach guardian: its watch, state, last run, summary line and open findings (master: the four watches)POST /api/v2/guardians/probe{note}: the security guardian asks before probing (guardians.probe: person E_SCOPE, asks 202 approval, tells runs)POST /api/v2/reports/<Report:topic>/send{finding: f1, line: 1}: a person ticking a suggested item (the checkbox is the button): makes it (links.report) and marks the line - [x] … → P-n; an AI token is E_SCOPEPOST /api/v2/pipeline/<id>/answer{answer: approve | refuse, note?}: a person answers an approval item. On a kind: batch item it answers a review batch instead (^pipe-59): {section, ver, accept: true} | {section, ver, comment}, {all: true, ver} for every section still open, {text, ver} for one comment on the whole batch, {send: true} to pass on what is waiting. The person's, or their AI with askedBy; E_SECTION_CHANGED when the section has changed since, E_NO_SECTION when there is no such sectionPOST /api/v2/tokens/agent{name, follows?, ttl?} with your role token → 201 {token, agent, role, expires, mintedBy}: the name you are given is the one you asked for, or it with the next free number. The new token copies your person, role, level and scope; ttl (seconds) may only shorten it, and it never outlives your role token. An agent or tool token minting is E_SCOPE; at most 10 a minute. A dispatcher or the monitor renews instead of minting again (rank 15 below); every other role stops when its token ends. Header D2-Started-By: Bearer <the starter's own agent token> (a live dispatcher or monitor of yours): records startedBy on the new token, which lets that starter revoke it later even though a role token out of your vault is what minted it — any other kind, role, person or an ended one is E_ARG/E_SCOPEPOST /api/v2/tokens/agent/renewa dispatcher or the monitor only: your live agent token as the Bearer and your role token in D2-Role-Token → 201 {token, agent, role, expires, mintedBy, secrets, renewed: {was, now}}. The same name, a fresh lifetime from your role's row, your secrets re-sealed; the old token is revoked at once, so call it in your last sixth and use the new one from the next call on. Your board row, held items, for roles, stops and messages all stay, because the name is what they hang off. Any other role is E_SCOPE; an expired token is 401 E_AUTH — once it has ended nothing proves you are the same agent, so mint again and post follows: <your old name> on your first statusGET /api/v2/tokens/agentsthe agent tokens this token minted, newest first: {agent, role, created, expires, lastUsed, revoked, startedBy?, live} — never their values. An agent token lists none, because it minted noneDELETE /api/v2/tokens/agents/<agent>revoke a token by name: yourself (your own agent name, whatever your role — end your own run), one you minted, or one you started (its startedBy is your agent name — a dispatcher cleaning up a coder it minted with a role token out of the vault; the answer says started: true). Its next call is 401 E_AUTH, at once. Any other name you hold here is 403 E_SCOPE, saying what this token may revoke; a name nobody of yours holds here is 404 E_NOT_FOUND. Revoking a role token ends every agent it minted, at oncePOST /api/v2/tokens/agents/<agent>/suspendpause a token by name, the same ones DELETE may revoke (yourself, the agent tokens you minted, the agents you started) → {suspended, kind, self, already}: every call with it is refused 403 E_TOKEN_SUSPENDED until resumed; a paused role token's agents are paused with it. Nothing is re-minted, the expiry keeps running. /resume → {resumed, …}: the same token again. The person pauses any of theirs on the AI tokens page (Suspend beside Revoke). Both audited (A_TOKEN_SUSPEND, A_TOKEN_RESUME)GET /api/v2/cronsthe project's crons: {total, limits, data}; the Architect: ?all=1 every project's. Crons are made by rules: diesel.cron (name, schedule, tz, msg, args)POST /api/v2/crons/<name>/run | on | offadmins: run it now (a flow), or switch it on or offGET /embedthe sandboxed frame embedhtml widgets and framed apps run in, with a policy of its own; the page hands it the HTML (P-221)POST /mcpd2 as an MCP server: Streamable HTTP, stateless; tools whoami, pipeline_*, agent_status, messages_read, message_send, changes_since, topic_*, memory_*, skill_*; claude mcp add --transport http d2 https://<project>.aiheroapps.com/mcp --header "Authorization: Bearer <token>"GET /api/v2/trashdeleted topics, kept 30 days: {total, days, data}POST /api/v2/trash/<name>/restoreput it back as it was, with its history; ?id= picks oneGET /api/v2/cdnthis project's files: {total, host, types, usage, data}; ?tag= ?prefix=GET /api/v2/cdn/<path>one file's record, with its urlPUT /api/v2/cdn/<path>upload (members); ?tags= ?access=public|membersPATCH /api/v2/cdn/<path>{tags, access}; its uploader or a modDELETE /api/v2/cdn/<path>its uploader or a modPOST /api/v2/diesel/parse{source} → {ok, errors, decls}POST /api/v2/diesel/expr{source, lenient?, ast?, vars?} → {ok, results[]}; one statement per line, open (no token): evaluation is purePOST /api/v2/diesel/resetback to the demo: topics, domain and objects reload from the seed topics; needs the tokenPOST /api/v2/diesel/run{spec, story, scratch?} → {ok, phase, errors, payload, flow, tests, trace}; spec/story are text or {topic}GET /api/v2/diesel/enginesthe last 5 flows: {total, keep, data}; HTML twin /flowsGET /api/v2/diesel/engines/<id>one flow: result, expects, trace, syntax tree; HTML twin /flows/<id>GET /api/v2/openspecthe OpenSpec topics as an openspec/ tree: {total, changes, files}, each checkedGET /api/v2/openspec/changes?spec=changes with status, date, deltas and tasksGET /api/v2/domain/overviewclasses, their links, enums, and the model checks (errors, warnings); HTML twin /domain/overviewGET /api/v2/domain/cat/*every class in full: fields, kinds, annotations, inverses, messagesGET /api/v2/domain/cat/A,Bsome classes in full; HTML twin /domain/cat/AGET /api/v2/dom/val/Companylist: {total, class, data}; ?query= an expression over the fields, ?limit= ?offset=; HTML twin /dom/val/CompanyGET /api/v2/dom/val/Company?query=stage%20is%20%22Producer%22the query in actionGET /api/v2/dom/val/Company:FLRone object by WPATH ([d2.]Class:key); HTML twin /dom/val/Company:FLRPUT|DELETE /api/v2/dom/val/Class:keyupsert (the URL key fills the key field) or delete; checked against the classPOST /api/v2/dom/val/Classcreate; 409 if the key existsPOST /api/v2/dom/batchmany objects across classes in one request: {mode: all | each, writes: [{op: put | create | delete, cls, key, data?}]} → {ok, written, results: [{i, cls, key, result}]}; mode all (the default) writes nothing if one is bad (422 E_VALIDATION); up to 200 writes and 2 MB (E_QUOTA); an AI token pays one write per 50 objectsGET|PUT|DELETE /api/v2/dom/<Class>/<key>the v0.1 form, kept as an aliasGET /api/v2/domain/overview?of=d2|basethe Architect only: the platform's own model or the base project'sGET /api/v2/mewho is asking, here: {project, known, email, role, god, join, tz}; an AI token answers for its person, with via: token. tz is the person's own time zone, IANA (null when unset): tell them times in it, never in UTCGET /api/v2/me/projectsYour projects, as the account home lists them: {projects: [{name, role, tags, pinned, lastUsed}], tags, filter}, pinned first, then by last used. Tags and pins are yours alone; no other member sees themPUT /api/v2/me/projects/<project>/tags{tags: [...]}: replace your tags on a project you're in. A tag is 1 to 30 lower-case letters, digits or dashes; at most 20 a project and 100 different ones in all (E_ARG); a project you aren't in is E_NOT_MEMBERPUT /api/v2/me/projects/<project>/pin{pinned: true|false}: pin it to the top of Your projects; E_NOT_MEMBER as abovePUT /api/v2/me/projects/filter{tags: [...]}: the tags selected on Your projects (it lists the projects having all of them), kept so the page reopens as leftGET /api/v2/notices/stamp{stamp, n} of what's waiting for you (notices, things to act on; n: how many): the Notices page syncs on it, every page's navbar polls it for its countGET /api/v2/agents/stamp{stamp} of the project's agent board and your messages: the Agents page and the pipe map sync on itGET /api/v2/projects/available?name={available} or {available: false, code, reason}POST /api/v2/project/release{version}: a new version of this project (admins)DELETE /api/v2/project{name}: delete this project and all its data, its name typed to confirm (its owner or an admin, in their session; never a token, never a built-in project)GET /api/v2/auth{loggedIn, tokenNeeded}: the write token's cookiePOST /api/v2/auth/loginretired (P-434): 410 E_MOVED — a browser logs in at /login, a token goes in each call's Authorization headerPOST /api/v2/auth/logoutclears itGET /api/v2/tls-ask?domain=for the TLS proxy: 200 only for our namesPOST /api/v2/broadcasts{title (≤80), body (markdown subset ≤2000: paragraphs, **bold**, *italic*, links to https:// or a path), level?: info|warning, until?}: a draft → 201 {id, preview}; nobody is told yetGET /api/v2/broadcastsevery broadcast, newest first; /<id> one; PATCH /<id> changes a draft (E_STATUS once sent); DELETE /<id> drops a draftPOST /api/v2/broadcasts/<id>/sendone priority N_BROADCAST per account, behind notice.broadcast (his AI: asks); /withdraw takes it off everyone's Noticescurl -s https://ai-putty.com/api/v2/diesel/run \\
-H 'content-type: application/json' -H 'authorization: Bearer $D2_TOKEN' \\
-d '{"spec":"$when hello (who) => (payload = \\"hi \\" + who)","story":"$send hello (who = \\"d2\\")\\n$expect payload == \\"hi d2\\""}'
Reads and diesel/expr are open; other writes (PUT, POST, DELETE) need a bearer token. Log in, sign up, members, tokens and the account pages are HTML forms (the pages; see Help). Admin API (/admin/*: status, logs, deploy, restart, rollback) is separate and token-only.