DermLiving
All posts

Product6 min readBy DermLiving

DermLiving makes dermatology programmable

Payments, messaging and maps became programmable when they got APIs. DermLiving does the same for dermatology knowledge: IDs, codes, cited answers and refusals your code can act on.

In short

Programmable means software can call dermatology knowledge and act on the result. DermLiving returns conditions with stable IDs and ICD-10-CM and ICD-11 codes, answers split into cited claims, refusals with a reason code, and knowledge versions a request can pin. Code can branch on each field instead of parsing prose. Today it runs on a synthetic sandbox.

Card payments, text messages and maps each became programmable when someone put an API in front of them. Developers stopped negotiating with banks, carriers and map makers, and started calling endpoints they could test, version and ship.

Dermatology knowledge has not had that moment. It lives in textbooks, guidelines, code sets and the heads of clinicians. Software that needs it today has two options. It can hard-code what it needs, which goes stale without anyone noticing. Or it can ask a general-purpose model and get prose back: no source to check, no version to pin, and no reliable way to tell a careful answer from a confident guess.

DermLiving makes dermatology programmable. Every answer is data your code can read, check and act on. Here is what that means, one field at a time.

Concepts have IDs, not only names

A name is for people. An ID is for code. Ask for atopic dermatitis and you get one record with a stable ID and its codes in two systems: ICD-10-CM, used for diagnosis coding in the United States, and ICD-11, the WHO's current classification.

bash
curl https://api.dermliving.com/v1/conditions/cond_atopic_dermatitis
json
{  "data": {    "id": "cond_atopic_dermatitis",    "name": "Atopic dermatitis",    "synonyms": ["Atopic eczema", "AD"],    "codes": [      { "system": "ICD-10-CM", "code": "L20.9", "display": "Atopic dermatitis, unspecified" },      { "system": "ICD-11", "code": "EA80.Z", "display": "Atopic eczema, unspecified" }    ],    "course": "chronic, relapsing",    "source_ids": ["src_sbx_ad_overview"]  },  "meta": { "knowledge_version": "kv_2026_10_01" }}

The record above is shortened. The full one also lists morphology, typical sites by age and an evidence count.

The terminology map works in the other direction. Send it L20.9 and it resolves to that one concept with a score of 1. Send it eczema and it returns two candidates and "ambiguous": true, because the lay word can mean more than one thing. What does eczema mean? walks through that case.

Answers are claims with sources

An answer from POST /v1/knowledge/ask is not a paragraph to trust. It is a list of claims, and each claim cites the passage behind it: the source, the source version, a locator such as "Distribution, para 2", a checksum and a license. Your code can render the citations as footnotes, check that a passage has not changed since it was cited, or refuse to show any claim that has none. Cite or abstain shows a full answer.

Refusals have reason codes

Every answer has a status: grounded or abstained. An abstention carries a reason and no answer. Ask which treatment a patient should start:

json
{  "data": {    "status": "abstained",    "reason": "clinical_decision",    "answer": null,    "message": "Treatment and diagnosis are clinical decisions. DermLiving returns reference knowledge only.",    "citations": []  },  "meta": { "request_id": "req_Ift5j8oDpA", "knowledge_version": "kv_2026_10_01" }}

There are three reasons, and each comes with a plain message:

ReasonWhenMessage
clinical_decisionThe question asks for a diagnosis or a treatmentTreatment and diagnosis are clinical decisions. DermLiving returns reference knowledge only.
insufficient_evidenceNo passage supports an answerNo passage in kv_2026_10_01 supports an answer.
patient_dataThe question appears to hold patient identifiersThe question appears to contain patient identifiers. Send reference questions only; nothing was stored.

A model that declines in prose has to be parsed, and it may phrase the refusal differently tomorrow. A reason code does not change. Your app can handle each one the same way every time: show a message, hand off to a person, or leave the feature out for that request.

Knowledge has versions you can pin

Every response names the knowledge version it read, in meta.knowledge_version. GET /v1/knowledge/versions lists the snapshots, and an answer request can pin one:

bash
curl https://api.dermliving.com/v1/knowledge/ask \  -H 'content-type: application/json' \  -d '{"question": "Where does atopic dermatitis usually appear in adults?", "knowledge_version": "kv_2026_09_01"}'

Pinned to the September snapshot, the same question returns one claim instead of two, because the passage behind the second claim arrived in October:

json
{  "data": {    "status": "grounded",    "answer": "In adults, atopic dermatitis favors flexural skin, the neck, face and hands. [1]"  },  "meta": { "knowledge_version": "kv_2026_09_01" }}

The response above is shortened to the status, the answer and its version. Pinning means an answer your tests approved yesterday is the answer you get today. You move to a new version when you choose to, after you have seen what it changes. A pin to a version that does not exist gets a VERSION_NOT_FOUND error, never a silent fallback. In the sandbox, both snapshots hold synthetic data.

Sources carry their rights

Whether you may store a passage, embed it, show a snippet, show the full text or train on it depends on its license. DermLiving returns those five rights as fields on every source:

json
{  "data": {    "id": "src_sbx_ad_overview",    "publisher": "DermLiving Sandbox Reference",    "synthetic": true,    "versions": ["sv_2026_09_14", "sv_2026_08_30"],    "license": {      "id": "lic_sbx_synthetic",      "store": true,      "embed": true,      "display_snippets": true,      "display_full_text": "entitlement",      "train": false    }  }}

The response above is shortened. Your code can check display_full_text before it renders a passage, instead of leaving the question to a policy document. In the sandbox the license is synthetic. When licensed sources arrive, each one's rights will be recorded before it is indexed.

Agents get tools with scopes

The same knowledge is served to AI agents over the Model Context Protocol, as five read-only tools at https://api.dermliving.com/mcp. Each tool declares the scope it needs and runs through the same gateway as the REST API, with the same refusals. Giving AI agents dermatology tools covers the details.

What programmable does not mean

It does not mean automated care. DermLiving returns reference knowledge. It does not diagnose, score malignancy, choose or dose treatment, or triage, and it refuses patient data. Making the knowledge programmable is what makes that boundary enforceable: the refusal is part of the contract, so every app built on it inherits the same limits.

It also does not mean the content is clinical yet. Today the API serves a small synthetic dataset, published as DermLiving Sandbox Reference, so you can build against the real shape of every response. It is not for patient care. Licensed sources, keys with their own scopes, and published SDKs are planned, and none of them is live.

Try it

No key and no sign-up:

bash
curl https://api.dermliving.com/v1/knowledge/ask \  -H 'content-type: application/json' \  -d '{"question": "Where does atopic dermatitis usually appear in adults?"}'

The quickstart covers every route, the playground runs them in your browser, and the contract is published as OpenAPI 3.1.

Questions

What does it mean to make dermatology programmable?

It means software can call dermatology knowledge as an API and act on structured results: concept IDs and codes, claims with citations, refusals with reason codes and versions it can pin, instead of parsing prose.

Does programmable dermatology mean automated diagnosis?

No. DermLiving returns reference knowledge. A question that asks for a diagnosis or a treatment gets an abstention with reason clinical_decision and no answer.

Which code systems does DermLiving map to?

ICD-10-CM and ICD-11. Each condition record carries codes in both, and the terminology map resolves a term or a code to concepts, with a flag when the input is ambiguous.

Can I pin the knowledge my app reads?

Yes, for answers. POST /v1/knowledge/ask accepts a knowledge_version, and every response names the version it read. In the sandbox, the snapshots hold synthetic data.

Is the sandbox content clinically reviewed?

No. The sandbox serves synthetic passages published as DermLiving Sandbox Reference, and it is not for patient care. Licensed sources, each with its rights recorded, are planned.

Sources

  1. DermLiving quickstart, DermLiving
  2. ICD-10-CM, U.S. Centers for Disease Control and Prevention, National Center for Health Statistics
  3. ICD-11, World Health Organization
  4. OpenAPI Specification v3.1.0, OpenAPI Initiative
  5. Model Context Protocol specification, version 2025-11-25, Model Context Protocol

Start in the sandbox.

The whole API on synthetic data. No key, no card, no patient data.