DocMark’s /v1 API turns your content into a branded, verified document — deck, Word, Excel, brochure, or newsletter — in your (or your customer’s) corporate brand. Your software authors the content; DocMark renders the design deterministically and verifies the output before returning it.

Availability. The managed cloud API is available now, and API access is included in every plan/v1 draws on the same monthly render credits. Tokens are issued by hand while we onboard teams personally: email hello@docmark.md and we will set one up. The same API also runs self-managed — on-prem or your own cloud tenant (deployment modes).

Authentication

Every request carries a bearer token scoped to one tenant:

Authorization: Bearer <your-api-token>

Tokens are issued per tenant. An auth failure never distinguishes between missing, malformed and revoked — no oracle — but the status code differs by endpoint: submitting returns 403 ({"error": "invalid or missing API token"}), while GET /v1/usage returns 401. Handle both if you key retry or token-refresh logic on the status code.

Submit a job — POST /v1/jobs

Send a job spec; get back a job id. The request is strictly validated — unknown keys are rejected (so a typo fails loudly instead of silently doing the wrong thing).

curl -sS https://docmark-api.happyriver-6d7d834c.australiaeast.azurecontainerapps.io/v1/jobs \
  -H "Authorization: Bearer $DOCMARK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
        "theme": "slate",
        "type": "brochure",
        "topic": "Q3 workplace strategy for a national occupier",
        "pages": 2
      }'
# -> { "job_id": "job_...", "state": "pending", "contract_version": "1.14.0" }

Request fields

theme is the only required field. Everything else is optional, and unknown keys are rejected.

FieldTypeApplies toNotes
themestringallRequired. Preset name; membership validated server-side.
typestringalldeck (default) · docx · xlsx · brochure · newsletter · video
topicstringdeckFree-text topic. At least one of topic or content is required.
contentarraydeckStructured sections, rendered verbatim — never re-authored by AI. Not read on docx or brochure — those author from topic. For a faithful document, use markdown.
markdownstringdocxCaller-prepared Markdown rendered faithfully to a branded .docx, AI off — the model never rewrites your words.
titlestringallMax 200 chars. xlsx uses it as the workbook title.
subtitlestringallMax 160 chars.
profilestringallDesign profile — a look variant of the same brand, e.g. engineering.
pagesintegerbrochure1–4, honoured exactly. Absent = 1.
chartsarraydeckCaller-authored chart specs: {kind: bar|line|pie, title, categories, series}
sheetsarrayxlsxCaller-authored sheets — tables and/or native charts.
itemsarraynewsletterUpdate items {heading, body}. Caps enforced server-side.
introstringnewsletterIntro paragraph.
issuestringnewsletterDated standfirst, e.g. Product update · June 2026.
footerstringnewsletterFooter line.
languagestringvideoen (default) or zh (Simplified Chinese). Narration and slide-text language. Any other value is rejected.
voicestringvideomale (default) or female.
web_searchbooleandeck, brochureServer-side search while authoring. API-mode workers only.
input_blobsarraydeckJob-scoped input files for spreadsheet→chart extraction (contract 1.6.0+).
tenantstringoperator onlyRender another tenant’s brand. Honoured only for entitled operator tokens.

The full machine-readable shape, including response types, is in job.schema.json.

type: "video" is a premium, entitlement-gated output: unless your tenant is entitled to video, a video submit is rejected with 402 before it is enqueued (default-deny). Ask us to enable video on your account; all other types are available to any valid token.

Poll status — GET /v1/jobs/{id}

curl -sS https://docmark-api.happyriver-6d7d834c.australiaeast.azurecontainerapps.io/v1/jobs/job_... -H "Authorization: Bearer $DOCMARK_TOKEN"
# -> { "state": "pending" | "processing" | "done" | "failed", "findings": "...", "provenance": {...}, ... }
  • state: "pending" | "processing" — still queued or mid-render; keep polling.
  • state: "done" — the artifact is ready; fetch it below.
  • state: "failed" — the job carries findings: a string, up to 2000 characters, giving the recorded reason the job failed. A verification-gate withhold puts its machine-readable findings JSON here; any other failure (a render error, a rejected spec) puts its reason. Fix and resubmit.
  • provenance — on a done job, a manifest of exactly which brand version, design profile, and engine produced the artifact. Best-effort: the key is absent when the sidecar is missing or unreadable (older results, custom queues), so read it defensively rather than assuming it is there.

Fetch the artifact — GET /v1/jobs/{id}/result

Returns the raw bytes with the correct content type (.pptx / .docx / .xlsx / .pdf / .png / .mp4). A 409 means “authorized but not rendered yet — keep polling.”

Submit and wait — POST /v1/jobs:render

A convenience wrapper for short jobs: submits through the same path and blocks until the artifact is ready, returning the bytes directly (?timeout_s=, clamped 5–120, default 90). On timeout it returns 202 and the job keeps running — poll GET /v1/jobs/{id}. Async-only types (video, newsletter, brochure) are rejected here; use the async submit for those.

Usage — GET /v1/usage

Your token’s own tenant render-budget usage: the daily sliding-window count plus your monthly quota (monthly_used, monthly_quota, monthly_unlimited, resets_at). Bearer-auth only; a dedicated read rate limit that never consumes your submit budget.

Rate limits & quotas

Each render debits one credit against your monthly quota (Individual 20, Studio 50, Team 300), with a derived daily burst cap. When a limit is reached, a submit is rejected with 429 before it is enqueued — code credit_exhausted (daily burst) or monthly_quota_reached (monthly quota) — each carrying a Retry-After header and an upgrade_url. Check current consumption with GET /v1/usage.

The job contract is versioned

Every response echoes contract_version (currently 1.14.0). The wire schema is producer-owned and pinned by conformance tests, so your integration won’t silently break — additive fields bump the minor version, and the schema is published for codegen: job.schema.json.

The verification promise

DocMark withholds a deliverable that fails its structural/visual gates rather than shipping a broken one. A withheld job fails with findings your agent or code can act on — the same loop a human would run, automated. This is the difference between “an AI made a slide” and “a verified, on-brand document your customer can send.”


Next: connect your AI agent over MCP · deployment modes & where the API runs · request access

See your brand, verified — in about a minute.

Type a topic and get a branded, verified sample. No account, no card. Then pick a plan or book a free brand defect review.

Try it free See pricing