API

Everything the CLI does goes through this HTTP API, and the CLI's --json output is the API's response bodies, so the two never disagree.

Authentication

Send a bearer token on every request:

export DROMAD_API_KEY=dmk_…   # Account › API keys; shown once
curl -s https://dromad.dev/api/v1/me -H "Authorization: Bearer $DROMAD_API_KEY"

API keys (dmk_…) are for servers, CI and agents; revoke them at Account › API keys. A key acts in one workspace, the one it was made for, and spends that workspace's credit: everything outside it is 404 to the key. The token dromad login stores (dct_…) is a per-device credential for a person, and reaches every workspace they belong to. GET /me lists the workspaces a credential can act in.

Keys can also be managed over the API: GET /api-keys lists them, with last_used_at and revoked_at; POST /api-keys with {"name": "…", "workspace_id": "ws_…"} creates one (for your own workspace if workspace_id is omitted) and returns the secret once, in key; DELETE /api-keys/{id} revokes one.

Errors

Every non-2xx response has one shape:

{"error": {"code": "conflict", "message": "Only a finished run can be shared; dr_… is queued.", "engine": null, "retryable": false}}

code is stable and machine-readable; message is for people; engine names the answer engine when one is at fault; retryable says whether the same request could succeed later. Treat an unknown code as its HTTP status.

Code Status Meaning
invalid_request 400 The request is malformed or asks for something impossible.
unauthenticated 401 No credential, or a revoked or unknown one.
insufficient_credit 402 The account's credit does not cover the request. Nothing was created; message gives what it needs, what is available and where to add credit. retryable is false.
permission_denied 403 The credential cannot do this.
not_found 404 No such object, or it is not yours.
conflict 409 The object is not in a state that allows this (sharing an unfinished run).
rate_limited 429 The account has too many runs queued or running at once. message gives the numbers; retryable is true.
engine_error 502 An answer engine failed; engine says which.
internal_error 500 Dromad failed.
cli_outdated 426 The request came from a dromad CLI older than the server supports. Nothing was run. See below.

An engine failing inside a prompt does not fail the request: that run is failed with its own error, and the batch is partial.

CLI versions. GET /version needs no credential and returns {"min_cli_version": "0.2.0"}, the oldest dromad CLI the server answers. The CLI names its version in User-Agent (dromad-cli/0.2.2), and a released version below the minimum gets cli_outdated from every other endpoint, before authentication and before anything is created or charged, because commands have changed meaning between versions. Only that User-Agent is checked: your own client is never refused for its version.

IDs and objects

IDs are <prefix>_<ULID> and sort by creation time: ws_ workspace, pr_ project, dr_ run, rq_ batch, fo_ fanout, fa_ questions analysis, ca_ citation analysis, sh_ share, ak_ API key. A run is one engine execution or one page audit; a batch is the runs one prompt request started; a fanout is the prompt runs of a set of prompts on several engines, repeated, with what each searched; an analysis is derived from runs. Finished runs and analyses never change.

Work is filed under a project, and a project belongs to a workspace (Teams). POST /prompts, /fanouts, /questions and /audits take "project": "pr_…" and answer 400 without it; GET /projects lists the ones a credential can use and POST /projects starts one. A citation analysis names no project: it is filed with its runs, which must all be in one. Runs and analyses report project_id and created_by; lists take ?project= and ?workspace=. Anything in a workspace the credential cannot act in is 404, the same as something that does not exist; 403 (permission_denied) means you are in the workspace and only an admin may do that.

Starting work and waiting for it

Work that calls an engine or fetches a page is queued, and the request returns at once:

Request Returns
POST /prompts 202 · the batch and its queued runs
POST /fanouts 202 · the queued fanout, its runs queued
POST /fanouts/estimate 200 · what that fanout would run and its estimated cost; informational, starts and authorizes nothing
POST /questions 202 · the queued questions analysis
POST /audits 202 · the queued audit run
POST /citation-analyses 201 · the finished analysis (it calls no model)

To wait, fetch the object with ?wait=N (0–30 seconds): the request returns as soon as the object finishes, or after N seconds with it still running. GET /runs/{id}, GET /batches/{id}, GET /fanouts/{id}, GET /analyses/{id} and GET /runs?batch=… all accept it.

AUTH="Authorization: Bearer $DROMAD_API_KEY"
batch=$(curl -s -X POST https://dromad.dev/api/v1/prompts -H "$AUTH" -H 'Content-Type: application/json' \
  -d '{"prompt": "best search APIs for AI agents", "engines": ["chatgpt", "claude", "gemini"], "project": "pr_…"}' | jq -r .batch.id)
curl -s "https://dromad.dev/api/v1/batches/$batch?wait=30" -H "$AUTH" | jq '.batch.status'

Run statuses are queued, running, completed and failed. A batch is completed when every run completed, partial when some failed, and failed when all did.

Pagination

GET /runs and GET /analyses return {"items": [...], "next_cursor": "…"}, newest first. Pass limit (1–200, default 50) and, for the next page, cursor=<next_cursor>. next_cursor is null on the last page.

Sharing

A finished run or analysis can have one public, read-only link. The same four requests exist under /runs/{id}/share and /analyses/{id}/share:

Request Does
GET …/share {"shared": true/false, "share": …}: whether a link is active, and which.
POST …/share Creates the link, or returns the active one. 409 conflict if the object has not finished.
POST …/share/rotate Replaces the link; the old one stops working.
DELETE …/share Stops sharing; the link stops working at once.

The share object's url is the page to hand out. Shared pages need no account and ask search engines not to index them.

Examples

# What engines search for a set of prompts. The estimate is informational: what
# decides whether the fanout starts is the workspace's available credit (402 if short).
BODY='{"prompts": [{"text": "free web search MCP server for Claude Code"}], "runs": 3, "project": "pr_…"}'
curl -s -X POST https://dromad.dev/api/v1/fanouts/estimate -H "$AUTH" -H 'Content-Type: application/json' -d "$BODY" \
  | jq '{executions, total_usd, available_usd, sufficient}'
fanout=$(curl -s -X POST https://dromad.dev/api/v1/fanouts -H "$AUTH" -H 'Content-Type: application/json' -d "$BODY" | jq -r .id)
curl -s "https://dromad.dev/api/v1/fanouts/$fanout?wait=30" -H "$AUTH" \
  | jq '.prompts[].engines[] | {engine, runs: [.runs[] | [.queries[].text]]}'

# Questions for a topic
curl -s -X POST https://dromad.dev/api/v1/questions -H "$AUTH" -H 'Content-Type: application/json' \
  -d '{"topic": "AI search API", "count": 30, "project": "pr_…"}'

# Count what a set of runs and batches cited
curl -s -X POST https://dromad.dev/api/v1/citation-analyses -H "$AUTH" -H 'Content-Type: application/json' \
  -d '{"ids": ["rq_…", "rq_…"], "domains": ["exa.ai"], "brands": ["Exa"]}'

# Audit a page
curl -s -X POST https://dromad.dev/api/v1/audits -H "$AUTH" -H 'Content-Type: application/json' \
  -d '{"url": "https://exa.ai/docs/reference/search", "project": "pr_…"}'

# Share a finished analysis
curl -s -X POST https://dromad.dev/api/v1/analyses/ca_…/share -H "$AUTH" | jq -r .url

Reference

Generated from /api/v1/openapi.json, the schema the API itself serves, so it cannot fall behind. Try requests in the interactive explorer.

Meta

GET /api/v1/version

The oldest `dromad` CLI this server answers. Needs no credential. An older CLI gets `cli_outdated` (HTTP 426) from every other endpoint, before anything is run or charged; other clients are not checked.

Auth
none
CLI
no command: compare it with `dromad --version`
200
ServerVersion

Account

GET /api/v1/me

The account and credential this request authenticated as.

Auth
bearer token
CLI
dromad whoami
200
Me

GET /api/v1/api-keys

List Api Keys

Auth
bearer token
CLI
Account › API keys, in the browser
200
ApiKeyList

POST /api/v1/api-keys

Create an API key that acts in workspace_id (your own workspace if omitted) and spends its credit. The response carries the key itself, once.

Auth
bearer token
CLI
Account › API keys, in the browser
Body
ApiKeyCreateRequest
201
ApiKeyCreated

DELETE /api/v1/api-keys/{key_id}

Revoke Api Key

Auth
bearer token
CLI
Account › API keys, in the browser
path: key_id
string · required
204
No Content

Cli auth

POST /api/v1/cli/auth/start

Start

Auth
none
CLI
dromad login
Body
CLIAuthStartRequest
200
CLIAuthStart

POST /api/v1/cli/auth/poll

Poll

Auth
none
CLI
dromad login
Body
CLIAuthPollRequest
200
CLIAuthPoll

DELETE /api/v1/cli/auth/token

Revoke the CLI token this request is authenticated with (dromad logout).

Auth
bearer token
CLI
dromad logout
204
No Content

Runs

POST /api/v1/prompts

Run a prompt on one or more engines. Returns the queued batch and its runs at once; wait for them with GET /batches/{id}?wait=30.

Auth
bearer token
CLI
dromad prompt "…"
Body
PromptRequest
202
PromptBatch

GET /api/v1/runs

Newest first, across every workspace this credential can act in. project or workspace narrows it; fanout filters to one fanout's runs and batch to one batch, and with wait (seconds, up to 30) the call holds until that batch has finished.

Auth
bearer token
CLI
dromad runs list
query: batch
string | null
query: fanout
string | null
query: project
string | null
query: workspace
string | null
query: limit
integer
query: cursor
string | null
query: wait
integer
200
RunList

GET /api/v1/runs/{run_id}

One run. With wait (seconds, up to 30) the call holds until it has finished.

Auth
bearer token
CLI
dromad runs show dr_…
path: run_id
string · required
query: wait
integer
200
Run

GET /api/v1/batches/{batch_id}

A batch and its runs. With wait (seconds, up to 30) the call holds until every run has finished.

Auth
bearer token
CLI
dromad runs list --batch rq_…
path: batch_id
string · required
query: wait
integer
200
PromptBatch

Analyses

POST /api/v1/citation-analyses

Count what a set of prompt runs cited. ids takes run IDs and batch IDs; the analysis is computed from stored results and returned complete.

Auth
bearer token
CLI
dromad citations rq_… dr_…
Body
CitationAnalysisRequest
201
CitationAnalysis

POST /api/v1/questions

Generate the questions people ask about a topic. Returns the queued analysis at once; wait for it with GET /analyses/{id}?wait=30.

Auth
bearer token
CLI
dromad questions "…"
Body
QuestionsRequest
202
QuestionsAnalysis

GET /api/v1/analyses

Newest first; kind filters (questions or citations), project or workspace narrows to one.

Auth
bearer token
CLI
dromad analyses list
query: kind
string | null
query: project
string | null
query: workspace
string | null
query: limit
integer
query: cursor
string | null
200
AnalysisList

GET /api/v1/analyses/{analysis_id}

One analysis. With wait (seconds, up to 30) the call holds until it has finished.

Auth
bearer token
CLI
dromad analyses show fa_…
path: analysis_id
string · required
query: wait
integer
200
any

Fanouts

POST /api/v1/fanouts/estimate

What a fanout would run and its estimated cost: prompts × engines × runs prompt runs, each at its engine's current prompt price. Informational: it starts nothing, holds nothing and is not a quote.

Auth
bearer token
CLI
dromad fanout "…" --estimate
Body
FanoutRequest
200
FanoutEstimate

POST /api/v1/fanouts

Run every prompt on every engine runs times, web search on, to record what each searched. Returns the queued fanout at once; wait for it with GET /fanouts/{id}?wait=30. The whole fanout is priced and its credit reserved at once: if the workspace's available credit does not cover all of it, none of it starts (insufficient_credit). Each run is then charged when it completes and released if it fails.

Auth
bearer token
CLI
dromad fanout "…"
Body
FanoutRequest
202
Fanout

GET /api/v1/fanouts

Newest first, without their observations. project or workspace narrows it.

Auth
bearer token
CLI
dromad fanouts list
query: project
string | null
query: workspace
string | null
query: limit
integer
query: cursor
string | null
200
FanoutList

GET /api/v1/fanouts/{fanout_id}

The fanout and every query observed, nested prompt → engine → run. With wait (seconds, up to 30) the call holds until every run has finished. Each run's answer, sources and raw envelope are on the run (GET /runs/{run_id}).

Auth
bearer token
CLI
dromad fanouts show fo_…
path: fanout_id
string · required
query: wait
integer
200
Fanout

Audits

POST /api/v1/audits

Audit one page. Returns the queued run at once; its result is the audit document once GET /runs/{id}?wait=30 reports it finished.

Auth
bearer token
CLI
dromad audit https://…
Body
AuditRequest
202
Run

Sharing

GET /api/v1/runs/{object_id}/share

Whether the object is shared, and its link if it is.

Auth
bearer token
path: object_id
string · required
200
ShareStatus

POST /api/v1/runs/{object_id}/share

Share with anyone who has the link. Only finished objects can be shared; asking again returns the same link.

Auth
bearer token
CLI
dromad share dr_…
path: object_id
string · required
200
ShareState

DELETE /api/v1/runs/{object_id}/share

Stop sharing: the link stops working at once.

Auth
bearer token
CLI
dromad unshare dr_…
path: object_id
string · required
204
No Content

POST /api/v1/runs/{object_id}/share/rotate

Replace the link: the old one stops working, the new one is returned.

Auth
bearer token
CLI
dromad share dr_… --rotate
path: object_id
string · required
200
ShareState

GET /api/v1/analyses/{object_id}/share

Whether the object is shared, and its link if it is.

Auth
bearer token
path: object_id
string · required
200
ShareStatus

POST /api/v1/analyses/{object_id}/share

Share with anyone who has the link. Only finished objects can be shared; asking again returns the same link.

Auth
bearer token
CLI
dromad share ca_…
path: object_id
string · required
200
ShareState

DELETE /api/v1/analyses/{object_id}/share

Stop sharing: the link stops working at once.

Auth
bearer token
CLI
dromad unshare ca_…
path: object_id
string · required
204
No Content

POST /api/v1/analyses/{object_id}/share/rotate

Replace the link: the old one stops working, the new one is returned.

Auth
bearer token
CLI
dromad share ca_… --rotate
path: object_id
string · required
200
ShareState

Billing

GET /api/v1/pricing

What each operation costs now. Needs no credential. A prompt on several engines costs the sum of its engines' prices.

Auth
none
CLI
dromad pricing
200
RateCard

GET /api/v1/billing

A workspace's credit: what it has, what is held for work in progress, and what new work can use. Your personal workspace unless workspace names another you belong to.

Auth
bearer token
CLI
dromad balance
query: workspace
string | null
200
BillingSummary

GET /api/v1/billing/transactions

Every change to the workspace's balance, newest first, with who caused it.

Auth
bearer token
CLI
Account › Billing, in the browser
query: workspace
string | null
query: limit
integer
query: cursor
string | null
200
TransactionList

GET /api/v1/billing/usage

What was charged, by day, product and engine. Work that failed was not charged and is not listed.

Auth
bearer token
CLI
Account › Billing, in the browser
query: workspace
string | null
query: days
integer
200
UsageReport

Workspaces

GET /api/v1/workspaces

The workspaces this credential can act in, your own first.

Auth
bearer token
CLI
dromad link
200
WorkspaceList

POST /api/v1/workspaces

Start a team workspace. You are its admin.

Auth
bearer token
CLI
Workspaces › New, in the browser
Body
WorkspaceCreateRequest
201
Workspace

GET /api/v1/workspaces/{workspace_id}

Get Workspace

Auth
bearer token
CLI
Workspace › Members, in the browser
path: workspace_id
string · required
200
Workspace

PATCH /api/v1/workspaces/{workspace_id}

Admins only.

Auth
bearer token
CLI
Workspace › Settings, in the browser
path: workspace_id
string · required
Body
WorkspaceUpdateRequest
200
Workspace

GET /api/v1/workspaces/{workspace_id}/members

List Members

Auth
bearer token
CLI
Workspace › Members, in the browser
path: workspace_id
string · required
200
MemberList

PATCH /api/v1/workspaces/{workspace_id}/members/{member_id}

Admins only. A workspace keeps at least one admin.

Auth
bearer token
CLI
Workspace › Members, in the browser
path: workspace_id
string · required
path: member_id
integer · required
Body
MemberUpdateRequest
200
Member

DELETE /api/v1/workspaces/{workspace_id}/members/{member_id}

An admin removes anyone; anyone removes themselves. Their work stays: it is the workspace's.

Auth
bearer token
CLI
Workspace › Members, in the browser
path: workspace_id
string · required
path: member_id
integer · required
204
No Content

GET /api/v1/workspaces/{workspace_id}/invitations

Admins only.

Auth
bearer token
CLI
Workspace › Members, in the browser
path: workspace_id
string · required
200
InvitationList

POST /api/v1/workspaces/{workspace_id}/invitations

Admins only. The response carries the link, once; it is also emailed when this server can send mail (emailed says whether it was).

Auth
bearer token
CLI
Workspace › Members, in the browser
path: workspace_id
string · required
Body
InvitationCreateRequest
201
InvitationCreated

DELETE /api/v1/workspaces/{workspace_id}/invitations/{invitation_id}

Revoke Invitation

Auth
bearer token
CLI
Workspace › Members, in the browser
path: workspace_id
string · required
path: invitation_id
string · required
204
No Content

Projects

GET /api/v1/projects

Every project this credential can see, by workspace; workspace narrows to one.

Auth
bearer token
CLI
dromad list
query: workspace
string | null
200
ProjectList

POST /api/v1/projects

Start a project. Any member of the workspace can.

Auth
bearer token
CLI
dromad init
Body
ProjectCreateRequest
201
Project

PATCH /api/v1/projects/{project_id}

Rename a project, or say what it is about. Any member can. context replaces the old one whole.

Auth
bearer token
CLI
Projects › the project, in the browser
path: project_id
string · required
Body
ProjectUpdateRequest
200
Project

GET /api/v1/projects/{project_id}

Get Project

Auth
bearer token
CLI
dromad status
path: project_id
string · required
200
Project

Schemas

AnalysisList

FieldTypeNotes
itemslist[AnalysisSummary]required
next_cursorstring | null

AnalysisSummary

FieldTypeNotes
idstringrequired
kindstringrequired
statusstringrequired
subjectstringrequired
project_idstring | null
created_bystring | null
run_countintegerrequired
created_atstring (date-time)required
completed_atstring (date-time) | null

ApiKey

FieldTypeNotes
idstringrequired
namestringrequired
prefixstringrequired
workspace_idstring | nullThe one workspace this key acts in and whose credit it spends.
created_atstring (date-time)required
last_used_atstring (date-time) | null
revoked_atstring (date-time) | null

ApiKeyCreateRequest

FieldTypeNotes
namestringrequired
workspace_idstring | nullWhere the key acts. Your own workspace if omitted.

ApiKeyCreated

Returned once, at creation. key is never retrievable again.

FieldTypeNotes
idstringrequired
namestringrequired
prefixstringrequired
workspace_idstring | nullThe one workspace this key acts in and whose credit it spends.
created_atstring (date-time)required
last_used_atstring (date-time) | null
revoked_atstring (date-time) | null
keystringrequired

ApiKeyList

FieldTypeNotes
itemslist[ApiKey]required

AuditContent

FieldTypeNotes
extraction_methodstring | nullWhich arm of the main-content cascade found the content.
word_countinteger
likely_js_dependentboolean | nullThe served HTML looks like a JavaScript shell (Dromad does not render JS).
excerptstring
blocksinteger
code_blocksinteger
tablesinteger
linksany
rendering_signalsobject

AuditDates

FieldTypeNotes
publishedstring | null
modifiedstring | null
last_modified_headerstring | null

AuditFetch

FieldTypeNotes
statusstringrequired · success, redirect, client_error, server_error, blocked, non_html, fetch_error
http_statusinteger | null
redirect_chainlist[RedirectHop]
content_typestring
server_headersdict[str, string]
elapsed_msinteger
errorstring | null
truncatedboolean
robots_txtRobotsTxt | null

AuditFinding

FieldTypeNotes
keystringrequired
versionintegerrequired
namestringrequired
categorystringrequired
severitystringrequired
evidence_levelstringrequired
statusstringrequired
reasonstring | null
itemslist[FindingItem]
why_it_mattersstringrequired
recommendationstringrequired

AuditMetadata

FieldTypeNotes
titlestring | null
descriptionstring | null
canonicalstring | null
langstring | null
robotsstring | null
x_robots_tagstring | null
noindexboolean | null
nofollowboolean | null
open_graphdict[str, string]
datesany
structured_data_typeslist[string]
structured_data_blocksinteger
structured_data_errorsinteger
markdown_alternateslist[string]
llms_txtlist[LlmsTxtProbe]

AuditPage

FieldTypeNotes
urlstringrequired · As requested.
final_urlstringrequired · Where the fetch landed after redirects.
domainstring | null

AuditRequest

FieldTypeNotes
urlstringrequired
projectstring | nullThe project to file this under (pr_…).

AuditResult

FieldTypeNotes
pageAuditPagerequired
fetchAuditFetchrequired
contentAuditContentrequired
structureAuditStructurerequired
metadataAuditMetadatarequired
findingslist[AuditFinding]required

AuditStructure

FieldTypeNotes
headingslist[Heading]The main-content outline, in order.
h1_countintegerh1 headings in the main content's outline. Whether the page has an h1 anywhere is the missing_h1 finding.
level_skipslist[LevelSkip]

Batch

FieldTypeNotes
idstringrequired
kindstringrequired
statusstringrequired
project_idstring | null
created_bystring | null
inputobjectrequired
run_idslist[string]required
created_atstring (date-time)required
updated_atstring (date-time)required

BillingSummary

FieldTypeNotes
workspace_idstring | nullWhose credit this is.
enabledbooleanrequired · False while this server charges for nothing.
balance_usdstringrequired · Purchased plus promotional credit.
purchased_usdstringrequired · Bought. Does not expire.
promotional_usdstringrequired · Given by Dromad. Spent first.
held_usdstringrequired · Set aside for work queued or running.
available_usdstringrequired · Balance less what is held: what new work can use.
spend_month_to_date_usdstringrequired · Charged since the 1st, UTC.
add_credit_urlstringrequired

CLIAuthPoll

FieldTypeNotes
statusstringrequired
tokenstring | null
token_idstring | null
emailstring | null

CLIAuthPollRequest

FieldTypeNotes
device_codestringrequired

CLIAuthStart

What the CLI shows the user, and the secret it polls with.

device_code never leaves the CLI; user_code is what the person compares in the browser before approving.

FieldTypeNotes
device_codestringrequired
user_codestringrequired
verification_uristringrequired
verification_uri_completestringrequired
expires_inintegerrequired
intervalintegerrequired

CLIAuthStartRequest

FieldTypeNotes
client_namestringrequired

CitationAnalysis

What a set of prompt runs cited. See :mod:`dromad.schemas.citations` for what each count means and how unknowns are reported.

FieldTypeNotes
idstringrequired
statusstringrequired
subjectstringrequired
project_idstring | nullThe project this is filed under. Null on a shared page.
created_bystring | nullWho made it, by email. Null on a shared page.
run_idslist[string]required
errorRunError | null
created_atstring (date-time)required
completed_atstring (date-time) | null
kindstring
methodstringrequired
brandslist[string]
target_domainslist[string]
totalsCitationTotalsrequired
engineslist[EngineSummary]
domainslist[DomainRow]
pageslist[PageRow]
overlapCitationOverlaprequired
retrieved_not_citedlist[SeenNotCited]
textual_mentionslist[TextualMention]
domain_coveragelist[DomainCoverage]
excluded_runslist[ExcludedRun]

CitationAnalysisRequest

FieldTypeNotes
idslist[string]required · Run IDs (dr_…) and/or batch IDs (rq_…); a batch contributes all its runs.
brandslist[string]Terms to count in answer text (naive, case-insensitive word match).
domainslist[string]Domains to report coverage for, e.g. exa.ai. Subdomains count.
use_project_contextbooleanWith no brands and no domains given, use the ones the runs' project records: its domains, and its brands and competitors as terms. What was used is in the analysis, as always.

CitationOverlap

FieldTypeNotes
enginesintegerrequired
domains_by_engine_countdict[str, integer]required · How many cited domains were cited by 1, 2, … engines.
pages_by_engine_countdict[str, integer]required
domains_cited_by_every_enginelist[string]required
pages_cited_by_every_enginelist[string]required

CitationTotals

FieldTypeNotes
runsintegerrequired
promptsintegerrequired
enginesintegerrequired
citationsintegerrequired
unique_cited_urlsintegerrequired
unique_cited_domainsintegerrequired
sources_observedintegerrequired · Every source any answer cited or listed.
retrieved_not_citedintegerrequired · Sources seen in search results or retrieval but not cited.
citation_status_unknownintegerrequired · Sources whose citation status the provider did not expose.
unresolved_sourcesintegerrequired · Redirect URLs that could not be resolved.
runs_without_citation_marksintegerrequired

Credential

The credential a request authenticated with.

FieldTypeNotes
kindstringrequired
idstringrequired
namestringrequired

DomainCoverage

FieldTypeNotes
domainstringrequired
runsintegerrequired
cited_runsintegerrequired
unknown_runsintegerrequired · Runs that did not cite it but whose citations were not exposed.
cited_ratenumberrequired · cited_runs / runs; a floor when unknown_runs > 0.
promptsintegerrequired
cited_promptsintegerrequired
citationsintegerrequired
pageslist[string]required
by_enginelist[EngineCoverage]required
prompts_citedlist[string]required
prompts_seen_not_citedlist[string]required · Prompts where it appeared in results but was never cited.
prompts_absentlist[string]required · Prompts where it never appeared at all.

DomainRow

FieldTypeNotes
domainstringrequired
citationsintegerrequired
pagesintegerrequired · Distinct cited pages on this domain.
runsintegerrequired
promptsintegerrequired
engineslist[string]required
seen_not_citedintegerrequired · Times it was seen in a run without being cited.

EngineCoverage

FieldTypeNotes
enginestringrequired
runsintegerrequired
cited_runsintegerrequired
unknown_runsintegerrequired

EngineSummary

FieldTypeNotes
enginestringrequired
runsintegerrequired
runs_with_citationsintegerrequired
citationsintegerrequired
unique_cited_domainsintegerrequired
runs_without_citation_marksintegerrequired

ExcludedRun

FieldTypeNotes
run_idstringrequired
reasonstringrequired

Fanout

FieldTypeNotes
idstringrequired
namestringrequired
statusstringrequired · Derived from the runs: queued, running, completed, partial or failed.
project_idstring | null
created_bystring | null
engineslist[string]required
runsintegerrequired
prompt_countintegerrequired
execution_countintegerrequired
countsdict[str, integer]required · Executions by run status.
query_countintegerrequired · Queries observed so far. Nothing is deduplicated.
created_atstring (date-time)required
completed_atstring (date-time) | nullWhen the last run finished, once all have.
held_usdstring | nullNull while billing is off.
charged_usdstring | null
promptslist[FanoutPromptObservations]required

FanoutEngineObservations

FieldTypeNotes
enginestringrequired
query_countintegerrequired · Queries observed across this engine's completed runs. Nothing is deduplicated.
runslist[FanoutRunObservation]required

FanoutEstimate

What a fanout would run, and what that is estimated to cost at the prices in effect now. For showing before starting; asking for one starts nothing. It is not a quote and authorizes nothing: what a fanout may start is decided when it is created, by the credit the workspace then has.

FieldTypeNotes
promptsintegerrequired
engineslist[string]required
runsintegerrequired
executionsintegerrequired · prompts × engines × runs: one prompt run each.
max_executionsintegerrequired · The most one fanout may run on this server.
identical_promptsintegerrequired · Prompts whose text repeats an earlier one. They are run all the same.
lineslist[FanoutEstimateLine]required
total_usdstringrequired · The estimated cost: every prompt run at its engine's current price. A run that fails is not charged.
pricing_versionstringrequired
billing_enabledbooleanrequired
available_usdstring | nullCredit the workspace can use now. Null while billing is off.
sufficientboolean | nullWhether that covers the total. Null while billing is off.

FanoutEstimateLine

FieldTypeNotes
enginestringrequired
executionsintegerrequired
unit_price_usdstringrequired
amount_usdstringrequired

FanoutList

FieldTypeNotes
itemslist[FanoutSummary]required
next_cursorstring | null

FanoutPromptInput

FieldTypeNotes
textstringrequired
sourceFanoutPromptSource | null

FanoutPromptObservations

FieldTypeNotes
positionintegerrequired · 1-based. How a prompt is addressed within its fanout.
textstringrequired
sourceFanoutPromptSource | null
engineslist[FanoutEngineObservations]required

FanoutPromptSource

Where a prompt came from, when it came from another Dromad object.

FieldTypeNotes
kindstring
analysis_idstringrequired
question_idstringrequired

FanoutRequest

FieldTypeNotes
namestring | nullDefaults to the first prompt.
promptslist[FanoutPromptInput]required · Kept exactly as given, in this order. A prompt given twice is run twice.
engineslist[string]
runsintegerIndependent executions of each prompt on each engine.
projectstring | nullThe project to file this under (pr_…).

FanoutRunObservation

One execution: what this engine searched this time.

FieldTypeNotes
run_idstringrequired
run_indexintegerrequired · 1-based: which repeat of this prompt on this engine.
statusstringrequired
modelstring | nullThe model the provider reported using.
searchedboolean | nullWhether the engine searched. Null if not recorded, or not done.
search_callsinteger | nullSearches it ran. More than the queries' calls if one showed no query text.
querieslist[ObservedQuery]
errorRunError | null
chargeRunCharge | null
created_atstring (date-time)required
started_atstring (date-time) | null
completed_atstring (date-time) | null

FanoutSummary

FieldTypeNotes
idstringrequired
namestringrequired
statusstringrequired · Derived from the runs: queued, running, completed, partial or failed.
project_idstring | null
created_bystring | null
engineslist[string]required
runsintegerrequired
prompt_countintegerrequired
execution_countintegerrequired
countsdict[str, integer]required · Executions by run status.
query_countintegerrequired · Queries observed so far. Nothing is deduplicated.
created_atstring (date-time)required
completed_atstring (date-time) | nullWhen the last run finished, once all have.

FindingEvidence

FieldTypeNotes
labelstringrequired
valueany
sourcestring

FindingItem

FieldTypeNotes
summarystringrequired
subtypestring | null
severitystringrequired
detailsobject
evidencelist[FindingEvidence]

Heading

FieldTypeNotes
levelintegerrequired
textstringrequired

Invitation

FieldTypeNotes
idstringrequired
emailstringrequired · Who the admin meant. The link, not the address, is what admits.
rolestringrequired
statusstringrequired · pending, accepted, revoked or expired.
invited_bystringrequired
accepted_bystring | nullWho took it, which may not be the address it was sent to.
created_atstring (date-time)required
expires_atstring (date-time)required

InvitationCreateRequest

FieldTypeNotes
emailstringrequired
rolestringadmin or member.

InvitationCreated

Returned once. url is the only copy of the link: Dromad keeps a hash.

FieldTypeNotes
idstringrequired
emailstringrequired · Who the admin meant. The link, not the address, is what admits.
rolestringrequired
statusstringrequired · pending, accepted, revoked or expired.
invited_bystringrequired
accepted_bystring | nullWho took it, which may not be the address it was sent to.
created_atstring (date-time)required
expires_atstring (date-time)required
urlstringrequired
emailedbooleanrequired · Whether Dromad sent it. If not, send the link yourself.

InvitationList

FieldTypeNotes
itemslist[Invitation]required

LevelSkip

FieldTypeNotes
from_levelintegerrequired
to_levelintegerrequired
atstringrequired

LinkCounts

Links to http(s) pages. Same-page anchors (#section) and mailto:, tel: and javascript: hrefs are not links here, so an API reference whose body only links to its own parameters has main: 0.

FieldTypeNotes
totalinteger
mainintegerIn the main content.
navigationintegerIn nav, header, footer and sidebars.
internalinteger
externalinteger

LlmsTxtProbe

FieldTypeNotes
kindstringrequired
urlstringrequired
http_statusinteger | null
foundbooleanrequired · A 200 whose body is not an HTML page.
linksinteger

Me

FieldTypeNotes
emailstringrequired
credentialCredentialrequired
workspaceslist[Workspace]Where this credential can act, your own first.

Member

FieldTypeNotes
idintegerrequired
emailstringrequired
namestring
rolestringrequired
joined_atstring (date-time)required

MemberList

FieldTypeNotes
itemslist[Member]required

MemberUpdateRequest

FieldTypeNotes
rolestringrequired · admin or member.

ObservedQuery

FieldTypeNotes
textstringrequired
positioninteger | null1-based place in the run's envelope. Null if not recorded.
search_callinteger | null1-based search call it was part of. Null if not recorded.
provider_search_idstring | null

PageRow

FieldTypeNotes
urlstringrequired
domainstring | null
titlestring | null
citationsintegerrequired
runsintegerrequired
promptsintegerrequired
engineslist[string]required

PriceRow

FieldTypeNotes
productstringrequired · prompt, questions, audit or citations.
enginestring | nullSet where the price depends on the engine.
unitstringrequired · What one unit is: prompt, question, url or analysis.
unit_price_usdstringrequired · Per unit. 0 means included.

Project

What a workspace is working on. Every member of the workspace sees it and everything filed under it; it never moves to another workspace.

FieldTypeNotes
idstringrequired
namestringrequired
slugstringrequired
workspace_idstringrequired
workspace_namestringrequired
contextany
created_bystringrequired
created_atstring (date-time)required

ProjectContext

What a project's work is about. Recorded, and shown wherever the project is; it changes what a command does only where that command says so.

FieldTypeNotes
primary_domainstring | null
domainslist[string]
brandslist[string]
competitorslist[string]

ProjectCreateRequest

FieldTypeNotes
namestringrequired
workspace_idstring | nullWhere to make it. Your own workspace (or the key's) if omitted.
contextProjectContext | null

ProjectList

FieldTypeNotes
itemslist[Project]required

ProjectUpdateRequest

FieldTypeNotes
namestring | null
contextProjectContext | nullReplaces the project's context whole.

PromptBatch

A prompt batch and its runs: the response to POST /prompts (runs queued) and, once finished, what dromad prompt --json prints.

FieldTypeNotes
batchBatchrequired
runslist[Run]required

PromptRequest

FieldTypeNotes
promptstringrequired
engineslist[string]
projectstring | nullThe project to file this under (pr_…).

PromptResult

What one engine answered, and the sources it showed.

FieldTypeNotes
answerstringrequired
sourceslist[SourceObservation]required
searcheslist[SearchObservation]required
citations_exposedbooleanrequired · Whether the answer carried any citation marks at all.
searchedboolean | nullWhether the engine searched the web. Null when that was not recorded.
search_callsinteger | nullHow many searches it ran; one search can carry several queries, or none the provider showed. Null when that was not recorded.

Question

FieldTypeNotes
idstringrequired
textstringrequired
cluster_idstringrequired
intentstringrequired
specificitystring | null

QuestionCluster

FieldTypeNotes
idstringrequired
namestringrequired
intentstringrequired
question_idslist[string]required

QuestionsAnalysis

FieldTypeNotes
idstringrequired
statusstringrequired
subjectstringrequired
project_idstring | nullThe project this is filed under. Null on a shared page.
created_bystring | nullWho made it, by email. Null on a shared page.
run_idslist[string]required
errorRunError | null
created_atstring (date-time)required
completed_atstring (date-time) | null
kindstring
topicstringrequired
requested_countintegerrequired
questionslist[Question]
clusterslist[QuestionCluster]
provenanceQuestionsProvenance | null
chargeRunCharge | nullHeld for requested_count, paid for the questions generated.

QuestionsProvenance

FieldTypeNotes
strategystringrequired
prompt_versionstringrequired
prompt_shastringrequired · SHA-256 of prompt_text.
prompt_textstringrequired · The full generation prompt, as sent.
modelstring | null
run_idstringrequired
generated_atstring (date-time)required

QuestionsRequest

FieldTypeNotes
topicstringrequired
countintegerHow many questions to ask for. Charged for those that come back.
projectstring | nullThe project to file this under (pr_…).

RateCard

The prices in effect. A prompt on several engines costs the sum of its engines' prices; there is no separate price for running all of them.

FieldTypeNotes
versionstringrequired
effective_fromstring (date-time)required
currencystring
priceslist[PriceRow]required

RedirectHop

FieldTypeNotes
urlstringrequired
statusintegerrequired
locationstringrequired

RobotsTxt

FieldTypeNotes
urlstringrequired
http_statusinteger | null
foundbooleanrequired
allows_pageboolean | nullrequired · Whether robots.txt lets Dromad fetch the page.

Run

FieldTypeNotes
idstringrequired
kindstringrequired
statusstringrequired
enginestring | null
modelstring | nullThe model the provider reported using.
batch_idstring | null
fanout_idstring | nullThe fanout this run is one execution of, if any.
project_idstring | nullThe project this run is filed under. Null on a shared page.
created_bystring | nullWho ran it, by email. Null on a shared page.
inputobjectrequired
resultPromptResult | AuditResult | null
errorRunError | null
usageUsage | null
chargeRunCharge | nullWhat this run costs the account. Null if it was not billable.
cost_usdnumber | nullNo longer reported: always null. See `charge`.
duration_msinteger | null
created_atstring (date-time)required
started_atstring (date-time) | null
completed_atstring (date-time) | null

RunCharge

What one run costs the account. held while the work is queued or running: that much credit is set aside. Then captured (paid; a set of questions pays for the questions it generated, which can be fewer than it held for) or released (the work failed and cost nothing).

FieldTypeNotes
statusstringrequired · held, captured or released.
amount_usdstringrequired · Held while held; paid once captured; 0 if released.
unitstringrequired
unitsintegerrequired
unit_price_usdstringrequired
pricing_versionstringrequired

RunError

FieldTypeNotes
codestringrequired
messagestringrequired
enginestring | null
retryableboolean

RunList

FieldTypeNotes
itemslist[RunSummary]required
next_cursorstring | null

RunSummary

FieldTypeNotes
idstringrequired
kindstringrequired
statusstringrequired
enginestring | null
batch_idstring | null
fanout_idstring | null
project_idstring | null
created_bystring | null
subjectstringrequired · The prompt text, or what else the run was about.
source_countinteger | null
cited_countinteger | null
created_atstring (date-time)required
completed_atstring (date-time) | null

SearchObservation

One query the engine searched, as the provider showed it.

Providers order their search calls; several queries inside one call were issued together and have no order among themselves. The three provenance fields are null on a run recorded before they were kept.

FieldTypeNotes
querystringrequired
positioninteger | null1-based place in the envelope, across the run.
search_callinteger | null1-based search call the query belongs to.
provider_search_idstring | nullThe provider's own ID for that search call.

SeenNotCited

FieldTypeNotes
urlstringrequired
domainstring | null
runsintegerrequired
engineslist[string]required

ServerVersion

FieldTypeNotes
min_cli_versionstringrequired

ShareState

FieldTypeNotes
idstringrequired
urlstringrequired · The public page. Anyone with it can read the object.
target_idstringrequired
target_kindstringrequired · run or analysis
created_atstring (date-time)required
revoked_atstring (date-time) | null
rotated_fromstring | null

ShareStatus

FieldTypeNotes
sharedbooleanrequired
shareShareState | null

SourceObservation

FieldTypeNotes
urlstringrequired
raw_urlstringrequired · The URL exactly as the engine returned it.
resolutionstringrequired
domainstring | nullrequired · Registered domain of `url`; null if unresolved.
domain_hintstring | nullFor an unresolved redirect, the domain the engine's title named. A hint only.
titlestring | null
citedboolean | nullrequired
citation_countinteger
citation_positionslist[integer]1-based positions in the answer's sequence of citations.
search_query_observedboolean | nullrequired · Appeared in the results of a search the engine ran.
retrieval_observedboolean | nullrequired · The provider showed that the page's content reached the model.

TextualMention

Naive by design: a case-insensitive whole-word match of the term in answer text. A single-word brand that is also an ordinary word, or a brand written differently, will be miscounted.

FieldTypeNotes
termstringrequired
runs_mentioningintegerrequired
runsintegerrequired
prompts_mentioningintegerrequired
promptsintegerrequired
occurrencesintegerrequired
runs_mentioning_by_enginedict[str, integer]required

Transaction

One change to the balance. Holds are not transactions: only money that moved is.

FieldTypeNotes
idstringrequired
kindstringrequired · promo_grant, purchase, usage, reversal or adjustment.
bucketstringrequired · promo or purchased.
amount_usdstringrequired · Signed: above zero adds credit.
descriptionstringrequired
operation_idstring | nullFor usage: the batch, analysis or run that was charged.
run_idstring | null
actorstring | nullWho spent or bought it, by email. Null for credit Dromad gave.
api_key_idstring | nullThe API key the charged work was started with, if any.
created_atstring (date-time)required

TransactionList

FieldTypeNotes
itemslist[Transaction]required
next_cursorstring | null

Usage

FieldTypeNotes
input_tokensinteger | null
output_tokensinteger | null
reasoning_tokensinteger | null
total_tokensinteger | null
web_searchesinteger | null

UsageReport

FieldTypeNotes
daysintegerrequired
total_usdstringrequired
rowslist[UsageRow]required

UsageRow

FieldTypeNotes
daystring (date)required
productstringrequired
enginestring | null
unitstringrequired
operationsintegerrequired · Runs that were charged.
unitsintegerrequired
charged_usdstringrequired

Workspace

FieldTypeNotes
idstringrequired
namestringrequired
kindstringrequired · personal (yours alone) or team.
rolestringrequired · Your role in it: admin or member.
created_atstring (date-time)required

WorkspaceCreateRequest

FieldTypeNotes
namestringrequired

WorkspaceList

FieldTypeNotes
itemslist[Workspace]required

WorkspaceUpdateRequest

FieldTypeNotes
namestringrequired