DUKTUS PRO API

Therapeutic AI for practice management software. GDPR-compliant, EU-hosted in Frankfurt.

Chat — Therapeutic AI
Send plain text with patient names. The API auto-anonymizes, runs the AI, returns the answer with names restored. The AI model never sees PII.
8–20 ct per call
POST/chat
Voice — Audio Transcription
Transcribe session recordings to text. EU backend keeps audio in Frankfurt. Optional automatic PII anonymization of the transcript.
12–18 ct per call
POST/voice/transcribe
GDPR
Hosted in Frankfurt, EU
AI never sees patient PII
Reversible anonymization
Art. 9 compliant
Voice: EU-only option available

What's available

ServiceDescriptionPrice
ChatTherapeutic AI with 5 modes — standard, diagnostics, planning, documentation, crisis8–20 ct
VoiceAudio-to-text transcription with optional PII anonymization. EU backend available.12–18 ct
AssessmentsPHQ-9, GAD-7, PCL-5, ISI, AUDIT-C scoring with clinical referencesFree
AnonymizerGDPR PII detection and reversible anonymization3 ct
EvidenceICD-10 disorder database, clinical guidelines, interventions0–10 ct
GeneratorClinical documents from 11 validated templates, PDF export20 ct
Text ImproveConvert shorthand notes into professional clinical language. Uses dkts_base_mini — smallest, fastest model6 ct

Base URL: https://api.duktus-pro.de/api/v1

GDPR & Data Privacy

DUKTUS PRO is built for healthcare. Every design decision prioritizes patient data protection.

The AI model never sees patient PII. Before any text is processed by the AI, names, dates of birth, addresses, phone numbers, insurance IDs, and other identifiers are replaced with neutral placeholders ([PERSON_1], [DATUM_1], etc.). The original values are restored in the response before it reaches your system.
MeasureDetail
EU InfrastructureAll services run in AWS eu-central-1 (Frankfurt, Germany)
Voice — EU optionbackend=private routes audio through our EU transcription service in Frankfurt. Audio never leaves the EU.
Reversible anonymizationEncrypted mappings are returned with every response — you can restore names at any time using /deanonymize
Art. 9 complianceDesigned for health-category data processing under GDPR Article 9
No AI training on your dataPatient conversations are not used to train the underlying models
Audit trailAll API calls are logged per-partner with timestamps for compliance audits

Authentication

All endpoints except GET /health require an API key in the request header.

HTTP Header
X-API-Key: dk_live_YOUR_40_CHAR_KEY

Keys are issued by DUKTUS PRO. Format: dk_live_ followed by 40 characters. Contact api@duktus-pro.de to request access.

Never include your API key in client-side code or commit it to version control. Contact us immediately to rotate a compromised key.

First API Call — Health Check

No authentication required. Confirm the API is reachable and all services are operational.

bash
curl https://api.duktus-pro.de/api/v1/health
python
import requests
r = requests.get("https://api.duktus-pro.de/api/v1/health")
print(r.json())
javascript
const r = await fetch('https://api.duktus-pro.de/api/v1/health');
const data = await r.json();
console.log(data.status); // "healthy"
response
{
  "status": "healthy",
  "api_version": "2.1.5",
  "services": {
    "anonymizer": { "status": "healthy" },
    "evidence":   { "status": "healthy" },
    "generator":  { "status": "healthy" }
  }
}

Chat — Therapeutic AI

The primary endpoint. Send clinical context in plain text — PII anonymization is automatic. You send patient names, the AI never sees them.

Modes

ModeUse casePrice
standardGeneral therapeutic questions15 ct
diagnostikICD-10 differential diagnosis20 ct
therapieplanungEvidence-based treatment planning20 ct
dokumentationSession notes and clinical reports8 ct
kriseninterventionCrisis assessment and safety planning20 ct
bash
curl -X POST https://api.duktus-pro.de/api/v1/chat \
  -H "X-API-Key: dk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Patient Maria Mueller, 34F, reports persistent insomnia for 3 weeks. PHQ-9: 12.",
    "mode": "diagnostik"
  }'
python
import requests

API_KEY = "dk_live_YOUR_KEY"
BASE    = "https://api.duktus-pro.de/api/v1"
headers = {"X-API-Key": API_KEY}

r = requests.post(f"{BASE}/chat", headers=headers, json={
    "message": "Patient Maria Mueller, 34F, persistent insomnia 3 weeks. PHQ-9: 12.",
    "mode": "diagnostik",
})

data = r.json()
print(data["response"])           # AI response -- names already restored
print(data["usage"]["cost_cents"])  # 20
print(data["session_id"])           # reuse for follow-up messages
javascript
const r = await fetch('https://api.duktus-pro.de/api/v1/chat', {
  method: 'POST',
  headers: { 'X-API-Key': 'dk_live_YOUR_KEY', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    message: 'Patient Maria Mueller, 34F, persistent insomnia 3 weeks.',
    mode: 'diagnostik',
  }),
});
const { response, session_id, usage } = await r.json();
console.log(response);           // AI response (names restored)
console.log(usage.cost_cents);   // 20

Multi-turn conversations

Pass session_id from the first response to maintain context across follow-up messages:

python
r1 = requests.post(f"{BASE}/chat", headers=headers,
    json={"message": "Patient Max Bauer, PHQ-9 score: 18.", "mode": "diagnostik"})

session_id = r1.json()["session_id"]

r2 = requests.post(f"{BASE}/chat", headers=headers,
    json={"message": "What therapy approach would you recommend?",
          "session_id": session_id})

Voice — Audio Transcription

Transcribe session recordings to text. The private backend processes audio in Frankfurt (EU) — audio never leaves the EU. Enable anonymize=true to strip PII from the transcript.

Backends

BackendSpeed (1h audio)Data locationGDPRPrice
fast (default) ~30–60 s Outside EU Not suitable for patient data 12 ct
private ~60–120 s EU (Frankfurt) GDPR-compliant 18 ct

Formats: WAV, MP3, WebM, M4A, FLAC, OGG (max 25 MB)  ·  Languages: de, en, fr, es, it, pt, nl, pl, tr, ru, ja, ko, zh

bash
# Fast (outside EU -- for non-patient data)
curl -X POST https://api.duktus-pro.de/api/v1/voice/transcribe \
  -H "X-API-Key: dk_live_YOUR_KEY" \
  -F "audio=@recording.mp3" \
  -F "language=de" \
  -F "backend=fast"

# GDPR-compliant (EU Frankfurt) + auto-anonymize
curl -X POST https://api.duktus-pro.de/api/v1/voice/transcribe \
  -H "X-API-Key: dk_live_YOUR_KEY" \
  -F "audio=@recording.mp3" \
  -F "language=de" \
  -F "backend=private" \
  -F "anonymize=true"
python
with open("recording.mp3", "rb") as f:
    r = requests.post(
        f"{BASE}/voice/transcribe",
        headers={"X-API-Key": API_KEY},
        files={"audio": ("recording.mp3", f, "audio/mpeg")},
        data={
            "language":  "de",
            "backend":   "private",  # EU/GDPR
            "anonymize": "true",     # strip PII from transcript
        },
    )

d = r.json()["data"]
# d["transcript"]                     -> full text
# d["duration_seconds"]               -> audio length in seconds
# d["anonymization"]["entities_found"] -> PII removed (if anonymize=true)
GDPR recommendation: For session recordings containing patient names, always use backend=private (Frankfurt, EU) and enable anonymize=true. This ensures audio stays in the EU and PII is stripped before the transcript is stored. Requires scope voice on your API key.

Assessments

Clinical scoring tools — completely free. Validated against clinical standards.

Supported: phq9 (9 items)  ·  gad7 (7 items)  ·  pcl5 (20 items)  ·  isi (7 items)  ·  auditc (3 items) — all values 0–3 per item.

python
r = requests.post(f"{BASE}/assessments/score", headers=headers, json={
    "tool":      "phq9",
    "responses": [2, 3, 2, 1, 2, 3, 2, 1, 1],  # 9 items, 0-3 each
})

d = r.json()["data"]
# d["score"]     -> 17
# d["severity"]  -> "Moderate Depression"
# d["reference"] -> "Loewe et al. 2002"
Include assessment scores in your Chat messages for richer responses: "PHQ-9: 17/27 (Moderate Depression). Patient reports..."

Anonymizer

Detects and reversibly replaces PII: names, dates of birth, addresses, phone numbers, IBANs, insurance IDs, email addresses. The Chat endpoint does this automatically — call /anonymize directly only for custom pipelines.

python
# Anonymize
r = requests.post(f"{BASE}/anonymize", headers=headers,
    json={"text": "Patient Maria Mueller, DOB 15.03.1985, Berlin."})

anon = r.json()["data"]
# anon["anonymized_text"]    -> "Patient [PERSON_1], DOB [DATUM_1], [ORT_1]."
# anon["mappings_encrypted"] -> "eyJ..."  -- store this to restore names later

# Deanonymize
r2 = requests.post(f"{BASE}/deanonymize", headers=headers, json={
    "anonymized_text":    anon["anonymized_text"],
    "mappings_encrypted": anon["mappings_encrypted"],
})
# -> "Patient Maria Mueller, DOB 15.03.1985, Berlin."

Evidence Database

Browse ICD-10-GM disorders, clinical guidelines, recommended interventions, and assessment tools. GET endpoints are free; full-text search costs 10 ct.

python
# Paginated disorder list (free)
requests.get(f"{BASE}/evidence/disorders?page=1&per_page=20", headers=headers)

# Disorder detail by ICD-10 code (free)
requests.get(f"{BASE}/evidence/disorders/F32", headers=headers)

# Recommended interventions (free)
requests.get(f"{BASE}/evidence/interventions/F32", headers=headers)

# Full-text search (10 ct)
requests.get(f"{BASE}/evidence/search?q=depression", headers=headers)

Document Generator

Generate clinical documents from 11 validated templates — session notes, risk assessments, treatment plans, and more. PDF export available.

python
# List templates
requests.get(f"{BASE}/generate/templates", headers=headers)

# Generate document (20 ct)
r = requests.post(f"{BASE}/generate/document", headers=headers, json={
    "template_id": "verlaufsdokumentation_enhanced",
    "context": {
        "patient_info": "35M, F32.1",
        "session_number": 5,
        "content": "Patient reports improved sleep. Exposure exercises successful.",
    },
})
# r.json()["data"]["document"] -> ready-to-use clinical text

Text Improve

Convert rough notes and shorthand into professional clinical documentation. Uses dkts_base_mini — the smallest, fastest model (EU Frankfurt, GDPR Art. 44-49). Output is always in German clinical language regardless of input language.

Output styles

StyleFormat
session_notesSession note — neutral, descriptive, present tense
reportAssessment report — formal, structured, past tense
letterReferral letter — very formal, full sentences
diagnosisDiagnostic formulation with explicit ICD-10-GM codes
general (default)General clinical language
python
r = requests.post(f"{BASE}/text/improve", headers=headers, json={
    "text":  "Pat. 34F, F32.1, 3 Monate, Schlafprob., Antriebslos.",
    "style": "session_notes",
})

d = r.json()["data"]
# d["improved"]  -> professional clinical text in German
# d["original"]  -> your input returned unchanged
print(d["improved"])
Pass the context field to hint at where the text will appear (e.g. "Treatment plan section 3: Goal definition") for better-calibrated output.

Extended Thinking

Add thinking: true to any Chat request to enable step-by-step reasoning. The AI works through the problem explicitly before responding — useful for complex diagnostic questions or treatment planning.

ParameterTypeDefaultNotes
thinkingbooleanfalseAdds +15 ct surcharge
thinking_budget_tokensinteger100001024 – 32000. Higher = deeper reasoning
python
response = requests.post(
    "https://api.duktus-pro.de/api/v1/chat",
    headers=headers,
    json={
        "message": "Patient shows F32.1 with somatic symptoms. PHQ-9: 18. GAD-7: 11. "
                   "Suggest a structured 12-session CBT plan including crisis protocol.",
        "mode": "therapieplanung",
        "thinking": True,
        "thinking_budget_tokens": 16000,
    }
)
data = response.json()

# Full reasoning trace (step-by-step)
print(data["thinking"])

# Final answer
print(data["message"])
bash
curl -X POST https://api.duktus-pro.de/api/v1/chat \
  -H "X-API-Key: $DUKTUS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Patient F32.1, PHQ-9 18, GAD-7 11. Suggest 12-session CBT plan.",
    "mode": "therapieplanung",
    "thinking": true,
    "thinking_budget_tokens": 16000
  }'
Cost: therapieplanung = 20 ct + 15 ct thinking surcharge = 35 ct total. Use standard mode (15 ct + 15 ct = 30 ct) for general thinking tasks.

Error Handling

All errors follow a consistent format with a machine-readable error.type and a human-readable error.message. Every response includes a request_id — include it when contacting support.

error response
{
  "type": "error",
  "error": {
    "type": "invalid_request_error",
    "message": "Field 'text' is required."
  },
  "request_id": "req_01abc..."
}
StatusMeaningAction
400Bad RequestFix your request body
401UnauthorizedCheck your X-API-Key
402Budget ExceededContact DUKTUS to increase your budget
404Not FoundCheck endpoint path and resource ID
422Validation ErrorCheck field types and allowed values
429Rate LimitedWait Retry-After seconds, then retry
500Server ErrorRetry once; contact api@duktus-pro.de with request_id
python — recommended error handling
import time, requests

def call_api(method, url, **kwargs):
    r = requests.request(method, url, **kwargs)
    if r.status_code == 429:
        time.sleep(int(r.headers.get("Retry-After", 60)))
        return call_api(method, url, **kwargs)  # retry once
    if r.status_code == 402:
        raise Exception("Monthly budget exceeded")
    r.raise_for_status()
    return r.json()

Rate Limits

Default: 100 requests/minute, 10,000/day per partner. Every response includes rate limit headers:

response headers
X-RateLimit-Limit-Minute:      100
X-RateLimit-Remaining-Minute:   87
X-RateLimit-Limit-Day:       10000
X-RateLimit-Remaining-Day:    9842
Retry-After:                     3  # only on 429

Pricing

Pay-per-use in EUR cents. Every response includes usage.cost_cents. HTTP 402 is returned when your monthly budget is reached.

EndpointPrice per call
POST /chat (standard)15 ct
POST /chat (diagnostik, therapieplanung, krisenintervention)20 ct
POST /chat (dokumentation)8 ct
POST /assessments/score, /toolsFree
POST /anonymize3 ct
POST /voice/transcribe (fast — outside EU, not for patient data)12 ct
POST /voice/transcribe (private — EU Frankfurt, GDPR-compliant)18 ct
GET /evidence/disorders/*, /interventions/*, /guidelinesFree
GET /evidence/search10 ct
POST /generate/document20 ct
POST /text/improve6 ct  dkts_base_mini