Type
A Type is an admin-curated Droplet noun (e.g. `recommendation`, `decision`, `incident`) that carries a schema of structured fields the platform renders, filters, and sorts. Each Droplet wears at most one Type.
The Type resource describes how Types live on Drop: Type names appear in each Droplet's Droplet.tags string array, with structured field values stored on App.typeFields keyed by Type name. The Type itself is a registry row with a schema declaring which primitive fields + custom fields its Droplets carry. See the Types concept doc for the why and the model.
The Type object
Every Type carries these attributes.
Attributes
recommendation). Unique within (scope, ownerId) — see scope / ownerId below. 2–50 chars, alphanumeric + hyphens, no colons (reserved for namespaced tags). May be created from scratch, or promoted up from an existing tag (USER → SPACE → GLOBAL).primitives is an opt-in subset of the system primitive registry; status (when opted in) declares the per-Type enum values; customFields is the array of Type-bound custom-field declarations. See the concept doc for the primitive registry shape.{
"id": "stg_recommendation",
"name": "recommendation",
"description": "A proposal awaiting decision. Carries status, progress, owner.",
"schema": {
"primitives": {
"status": {
"values": [
"draft",
"in-flight",
"decided",
"blocked"
]
},
"progress": true,
"priority": true,
"due": true,
"trafficLight": true,
"owner": true
},
"customFields": [
{
"key": "rice",
"type": "int",
"label": "RICE score"
},
{
"key": "quarter",
"type": "string",
"label": "Quarter"
}
]
},
"promotedById": "usr_kate",
"promotedAt": "2026-06-10T14:00:00.000Z",
"deprecatedAt": null
}Methods
Endpoints to operate on a Type. The example switches between curl, drop CLI, and MCP via the dropdown — your choice persists across the page.
List Types
Return the Type registry (admin-curated noun vocabulary). Demoted Types are excluded by default; pass includeDemoted=true to see them. For the free-form tag aggregate (non-Type names in use), see GET /api/tags / drop tags list.
Parameters
drop types list{
"types": [
{
"id": "tag_recommendation",
"name": "recommendation",
"description": "A proposal awaiting decision.",
"schema": {
"primitives": {
"status": {
"values": [
"draft",
"in-flight",
"decided"
]
},
"priority": true
},
"customFields": []
},
"promotedAt": "2026-06-04T18:00:00.000Z",
"deprecatedAt": null,
"promotedBy": {
"email": "jonathan@himarley.com",
"name": "Jonathan Tushman"
},
"usageCount": 6,
"scope": "GLOBAL",
"ownerId": null,
"promotedFromId": null
}
]
}Create a Type
Mint a new Type at the given scope (USER / SPACE / GLOBAL — see scope). USER scope is open to any authenticated user; SPACE requires Space admin on spaceSlug; GLOBAL requires LIBRARY_ADMIN. The schema declares which of the six primitive fields the Type uses (status / progress / priority / due / trafficLight / owner) and any custom key:value fields. status requires per-Type enum values; the other primitives canonicalize to true. Custom fields are capped at 30 per Type; enum values capped at 50 each.
Parameters
drop types create --name recommendation --description "A proposal awaiting decision." --schema "[object Object]" --scope GLOBAL{
"id": "tag_recommendation",
"name": "recommendation",
"description": "A proposal awaiting decision.",
"schema": {
"primitives": {
"status": {
"values": [
"draft",
"in-flight",
"decided"
]
},
"priority": true,
"due": true
},
"customFields": [
{
"key": "rationale",
"type": "markdown"
}
]
},
"promotedAt": "2026-06-04T18:00:00.000Z",
"deprecatedAt": null,
"promotedBy": {
"email": "jonathan@himarley.com",
"name": "Jonathan Tushman"
},
"usageCount": 0,
"scope": "GLOBAL",
"ownerId": null,
"promotedFromId": null
}Read a Droplet's typed field values
Return the per-Droplet typeFields JSONB blob along with the active Type schemas it references. Used by the detail-page strip and /view overlay to render structured-field widgets. Schemas are filtered to active Types — orphaned blocks for demoted Types appear in typeFields without a matching schema entry.
Parameters
drop types fields show q3-strategy-doc{
"typeFields": {
"recommendation": {
"status": "in-flight",
"priority": "high",
"progress": 65
}
},
"schemas": {
"recommendation": {
"primitives": {
"status": {
"values": [
"draft",
"in-flight",
"decided"
]
},
"priority": true,
"progress": true
},
"customFields": []
}
}
}Update a Type
Edit a Type schema or description. At least one of schema / description is required (omit both → 400 NO_CHANGES). Removing a status enum value that's still in use returns 409 STATUS_ENUM_VALUE_IN_USE with the affected Droplet list; retry with forceClearInUseStatus: true to proceed (clears those values).
Parameters
drop types edit recommendation --description "A proposal awaiting decision (revised)."{
"id": "tag_recommendation",
"name": "recommendation",
"description": "A proposal awaiting decision (revised).",
"schema": {
"primitives": {
"status": {
"values": [
"draft",
"in-flight",
"decided"
]
}
},
"customFields": []
},
"promotedAt": "2026-06-04T18:00:00.000Z",
"deprecatedAt": null,
"promotedBy": {
"email": "jonathan@himarley.com",
"name": "Jonathan Tushman"
},
"scope": "GLOBAL",
"ownerId": null,
"promotedFromId": null
}Demote a Type
Soft-delete a Type by setting deprecatedAt. Droplets that wore the Type keep its name in their tags array (now a plain tag) and retain their typed-field values in App.typeFields. A daily GC sweep deletes the orphaned field values 30 days after demotion — the retentionUntil field tells callers when. Reversible within the grace window via POST /api/types/{name}/restore.
Parameters
drop types demote experiment{
"name": "experiment",
"deprecatedAt": "2026-06-05T18:00:00.000Z",
"usageCount": 3,
"retentionUntil": "2026-07-05T18:00:00.000Z"
}Restore a demoted Type
Clear deprecatedAt on a demoted Type. Restores it as an active member of the registry; orphaned field-value blocks on Droplets become live again. Allowed within the 30-day post-demotion grace window only — beyond that returns 410 STRONG_TAG_DEMOTE_GRACE_EXPIRED with daysSince. Returns 409 STRONG_TAG_NOT_DEMOTED if the Type is already active.
Parameters
drop types restore experiment{
"name": "experiment",
"daysSinceDemoted": 3
}Set typed field values on a Droplet
Write one or more typed field values into the Droplet's App.typeFields blob, scoped to a single Type. The Type must already be in the Droplet's tags array (the type is opted-in by the chip rail, not by this endpoint). Values are coerced + validated against the Type's schema — null / empty string clears a key. Per-field errors return 400 TYPE_FIELD_* codes with { field } extras. Archived Droplets reject writes with 409 APP_ARCHIVED.
Parameters
tag).{key: value, ...} — null/"" clears a key.drop types fields set q3-strategy-doc --type recommendation --fields "[object Object]"{
"typeFields": {
"recommendation": {
"status": "in-flight",
"progress": 65,
"priority": "high"
}
},
"type": "recommendation",
"tag": "recommendation",
"block": {
"status": "in-flight",
"progress": 65,
"priority": "high"
}
}Promote a Type to a higher tier
Mint a copy of a USER or SPACE Type at a higher tier (USER → SPACE, or USER/SPACE → GLOBAL). The new Type row carries promotedFromId referencing the source; the source row is left in place. Promoting to GLOBAL requires LIBRARY_ADMIN; promoting to SPACE requires SPACE admin membership. Returns both the new Type and the source Type for client convenience.
Parameters
drop types promote-scope experiment --source-scope USER --source-owner-id usr_jonathan --target-scope GLOBAL{
"promoted": {
"id": "tag_experiment_global",
"name": "experiment",
"description": "An ongoing test.",
"schema": {
"primitives": {
"status": {
"values": [
"draft",
"running",
"done"
]
}
},
"customFields": []
},
"promotedAt": "2026-06-10T18:00:00.000Z",
"deprecatedAt": null,
"promotedBy": {
"email": "jonathan@himarley.com",
"name": "Jonathan Tushman"
},
"usageCount": 0,
"scope": "GLOBAL",
"ownerId": null,
"promotedFromId": "tag_experiment_user"
},
"source": {
"id": "tag_experiment_user",
"name": "experiment",
"description": "An ongoing test.",
"schema": {
"primitives": {
"status": {
"values": [
"draft",
"running",
"done"
]
}
},
"customFields": []
},
"promotedAt": "2026-06-04T18:00:00.000Z",
"deprecatedAt": null,
"promotedBy": {
"email": "jonathan@himarley.com",
"name": "Jonathan Tushman"
},
"usageCount": 4,
"scope": "USER",
"ownerId": "usr_jonathan",
"promotedFromId": null
}
}