Kamai · Schema
BlueprintDetailsResponse
ConstructionArtificial IntelligenceBlueprint ExtractionTakeoffEstimationRFI extractionSubmittal reviewSpec review
Properties
| Name | Type | Description |
|---|---|---|
| blueprint | object | Blueprint details |
| message | object | Additional information message |
| revision | object | The sheet's revision this copy was read at. Send it back as `base_revision` on a PUT that carries `geojson`: if the sheet changed in between, that save is refused with 409 `stale_sheet` instead of sil |
| integrity | object | The sheet's data-integrity mode, `{mode: legacy | adopted | derived, derivation}`. On a converted sheet the wall-surface pieces of a door or window are derived from it by the server and are read-only: |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://artifacts.apis.io/kamai-io/json-schema/kamai-io-blueprint-details-response-schema.json",
"title": "BlueprintDetailsResponse",
"x-generated": "2026-11-13",
"x-method": "derived",
"x-generator": "derive-json-schema.py",
"x-source": "openapi/kamai-io-openapi.json#/components/schemas/BlueprintDetailsResponse",
"properties": {
"blueprint": {
"$ref": "#/$defs/BlueprintPublic",
"description": "Blueprint details"
},
"message": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Message",
"description": "Additional information message"
},
"revision": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Revision",
"description": "The sheet's revision this copy was read at. Send it back as `base_revision` on a PUT that carries `geojson`: if the sheet changed in between, that save is refused with 409 `stale_sheet` instead of silently undoing the change. Opaque; compare for equality only."
},
"integrity": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"title": "Integrity",
"description": "The sheet's data-integrity mode, `{mode: legacy | adopted | derived, derivation}`. On a converted sheet the wall-surface pieces of a door or window are derived from it by the server and are read-only: edit the door or window. Absent while the feature is off."
}
},
"type": "object",
"required": [
"blueprint"
],
"$defs": {
"BlueprintFeaturePropertiesPublic": {
"properties": {
"id": {
"type": "string",
"title": "Id",
"description": "The feature's id, unique on this sheet. A re-analysis of the sheet issues new ids."
},
"kind": {
"$ref": "#/$defs/FeatureKind",
"description": "What the feature is geometrically: `area` (a polygon), `line`, `object` (a counted item such as a door or a sink) or `folder` (a group in the tree). Decides which measurements apply."
},
"class": {
"$ref": "#/$defs/FeatureClass",
"description": "What the feature is on the drawing: `room`, `wall`, `wall_centerline`, `wall_surface` (one room's side of a wall), `wall_surface_with_opening` (the piece of that side across a door or window), `opening` (doors and windows), `footprint` (the plan's outer boundary) or `other`."
},
"sub_class": {
"anyOf": [
{
"$ref": "#/$defs/FeatureSubClass"
},
{
"type": "null"
}
],
"description": "The specific type where known, e.g. 'single swing door', 'window', 'sink'. `wet room` and `wet wall` are derived from what a room contains (a toilet, a shower...), never detected, and are recomputed on every save."
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Name",
"description": "The label shown in the Kamai app, e.g. a room's name."
},
"color": {
"anyOf": [
{
"$ref": "#/$defs/FeatureColorPublic"
},
{
"type": "null"
}
],
"description": "Display colour in the Kamai app."
},
"visible": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Visible",
"description": "Visibility in this hierarchy."
},
"is_user_drawn": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Is User Drawn",
"description": "True when a user drew it rather than the detector."
},
"parent_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Parent Id",
"description": "Parent feature id; `null` on the root folder. With `position`, this is the ONLY hierarchy source — there is no reverse index."
},
"position": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"title": "Position",
"description": "Sort order among siblings. A float so an item can be inserted between two others without renumbering."
},
"folder": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Folder",
"description": "The parent's NAME — the group this feature lives under, resolved so grouping needs no client-side join over `parent_id`. `null` on roots and features outside the hierarchy."
},
"opening_width_units": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"title": "Opening Width Units",
"description": "Door/window clear width in blueprint units (the coordinate space of `geometry`). See `measurements.opening_width_m` for metres."
},
"wall_thickness_units": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"title": "Wall Thickness Units",
"description": "Walls (`class` `wall`) only: thickness face to face as drawn, in blueprint units. See `measurements.wall_thickness_m` for metres. `null` on every other class and where it was not measured. On PUT: a value replaces it, `null` clears it, and a wall that omits the key keeps its stored thickness while its geometry is unchanged (a reshaped wall drops it; where re-measuring is switched on it is re-measured from its new polygon instead, and a value a client sent is never re-measured over). A value on any other class is refused (422)."
},
"wall_thickness_source": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Wall Thickness Source",
"description": "Walls only: where `wall_thickness_units` came from. `null` = the pipeline's measurement; `measured_on_edit` = re-measured from the wall's polygon after it was reshaped or drawn by hand; `user` = a value a client sent. On PUT it says whose the sent `wall_thickness_units` is: omitted, `null` or `user` = a value you state (an unchanged number is an echo); `pipeline` or `measured_on_edit` = a machine figure you echo, never stored: a wall the sheet holds keeps its own thickness, and a re-added wall gets none. It is never stored as sent."
},
"wall_group": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Wall Group",
"description": "Walls, wall surfaces and surface-with-opening pieces: the texture group folder of the wall ('Group A'); a surface's is its wall's, read live. Read-only: ignored on PUT."
},
"height_units": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"title": "Height Units",
"description": "Optional vertical height in blueprint units, e.g. a room's or an opening's height read off the drawing. Send it back on a PUT to keep it."
},
"tag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Tag",
"description": "The mark printed beside a door or window on the drawing, e.g. 'D-01', 'W2' or '80/210'; `null` when none was read. Free text, and NOT an identifier: openings often share a mark, so never join or de-duplicate on it."
},
"handing": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Handing",
"description": "Single swing doors only: 'LH' or 'RH', read off the drawing's swing arc. It is the hinge side seen from the side the door swings away from (the push side, the North-American convention; European DIN handing is the mirror image). 'LHR'/'RHR' (reverse, pull-side handings) are never detected and are kept only when a client sets them. `null` on every other feature and where the arc could not be read. Round-trips unchanged on PUT. A value other than LH/RH/LHR/RHR is refused (422); on a feature that is not a single swing door it is dropped."
},
"handing_din": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Handing Din",
"description": "`handing` under DIN 107, the European convention, which names the hinge side seen from the side the door opens towards: 'DIN-L' (DIN links) or 'DIN-R' (DIN rechts). RH is DIN-L and LH is DIN-R (the mirror image); LHR is DIN-L and RHR is DIN-R. Derived from `handing` on every read and never stored: `null` wherever `handing` is, and ignored on PUT (set `handing` instead)."
},
"relations": {
"items": {
"type": "string"
},
"type": "array",
"title": "Relations",
"description": "Ids of features this one is spatially related to — an undirected edge set, so if A lists B then B lists A. Untyped by design: filter the ids by the neighbour's `class` for a typed view (a room's walls are the related ids whose class is `wall`/`wall_centerline`; its wall surfaces, cut at each opening on the room's side, are those whose class is `wall_surface`; the piece across a door/window is class `wall_surface_with_opening`; both turn `sub_class` `wet wall` with a wet room)."
},
"measurements": {
"$ref": "#/$defs/FeatureMeasurementsPublic",
"description": "Real-world size in m and m², derived by the server; read-only."
}
},
"type": "object",
"required": [
"id",
"kind",
"class"
],
"title": "BlueprintFeaturePropertiesPublic",
"description": "One feature's properties in the coarse feature shape."
},
"BlueprintFeaturePublic": {
"properties": {
"type": {
"type": "string",
"title": "Type",
"default": "Feature"
},
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Id"
},
"geometry": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"title": "Geometry",
"description": "GeoJSON geometry in blueprint units (see the blueprint's `url_width` and `url_height`), origin at the page's top-left corner. `null` for folders."
},
"properties": {
"$ref": "#/$defs/BlueprintFeaturePropertiesPublic"
}
},
"type": "object",
"required": [
"properties"
],
"title": "BlueprintFeaturePublic",
"description": "A GeoJSON Feature. `geometry` is `null` only for folders."
},
"BlueprintGeoJSONPublic": {
"properties": {
"type": {
"type": "string",
"title": "Type"
},
"features": {
"items": {
"$ref": "#/$defs/BlueprintFeaturePublic"
},
"type": "array",
"title": "Features"
}
},
"type": "object",
"required": [
"type"
],
"title": "BlueprintGeoJSONPublic"
},
"BlueprintPublic": {
"properties": {
"id": {
"type": "string",
"title": "Id",
"description": "The sheet's id (blueprint id)."
},
"name": {
"type": "string",
"title": "Name",
"description": "The sheet's stored name, usually its upload file name; GET /v1/projects/{id}/sheets gives the name the app shows."
},
"scale": {
"anyOf": [
{
"$ref": "#/$defs/BlueprintScalePublic"
},
{
"type": "null"
}
],
"description": "The sheet's drawing scale, which turns drawing distances into real lengths and areas. `null` means the sheet has no scale yet. On a sheet without a usable scale (none, a ratio that is not positive and finite, or no `url_dpi`), every `measurements` value is then `null`, never zero."
},
"url_height": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"title": "Url Height",
"description": "The sheet's height in blueprint units, the coordinate space of every `geometry`."
},
"url_width": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"title": "Url Width",
"description": "The sheet's width in blueprint units, the coordinate space of every `geometry`."
},
"url_dpi": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"title": "Url Dpi",
"description": "The resolution of the sheet image that feature coordinates are measured in (blueprint units per inch of paper). Together with the scale it converts drawing units to real ones. A sheet without `url_dpi` cannot be measured even if it has a scale: every `measurements` value is then `null`, never zero."
},
"geojson": {
"anyOf": [
{
"$ref": "#/$defs/BlueprintGeoJSONPublic"
},
{
"type": "null"
}
],
"description": "The sheet's features (rooms, walls, openings, objects) and their folder tree."
},
"text": {
"items": {
"$ref": "#/$defs/BlueprintTextPublic"
},
"type": "array",
"title": "Text",
"description": "The sheet's words. Read-only; ignored if sent on an update. Empty unless requested with `include_text`."
},
"text_total": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Text Total",
"description": "Total words on the sheet, which may exceed len(text) because the page is capped — page with text_limit/text_offset until you have seen this many. None when text was not requested."
},
"identity": {
"anyOf": [
{
"$ref": "#/$defs/SheetIdentityPublic"
},
{
"type": "null"
}
],
"description": "What the sheet says it is. Every key null and `levels` empty on a sheet that was not classified: not classified, never a guess."
},
"rotation": {
"type": "integer",
"title": "Rotation",
"description": "Degrees clockwise to turn the sheet for display: 0, 90, 180 or 270, relative to the tiles as served. A view setting: tiles, `url_width`/`url_height` and every `geometry` stay unturned, so apply it when you draw, to the image and the overlays alike. Set it with PUT /v1/blueprints/{blueprint_id}/rotation.",
"default": 0
},
"auto_rotation": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Auto Rotation",
"description": "Degrees clockwise (0, 90, 180, 270) Kamai turned the page at upload to bring it upright, on top of the PDF's own /Rotate. Already inside the tiles and every `geometry`: nothing to apply. Read-only. `null`: not decided (a sheet uploaded before the check existed)."
},
"created": {
"type": "string",
"format": "date-time",
"title": "Created",
"description": "When the sheet was created (ISO 8601)."
},
"updated": {
"type": "string",
"format": "date-time",
"title": "Updated",
"description": "When the sheet record last changed (ISO 8601)."
}
},
"type": "object",
"required": [
"id",
"name",
"created",
"updated"
],
"title": "BlueprintPublic"
},
"BlueprintScalePublic": {
"properties": {
"drawing": {
"type": "number",
"exclusiveMinimum": 0.0,
"title": "Drawing",
"description": "The drawing side of the scale ratio: the 1 in \"1:50\", or the ¼ inch in 1/4\" = 1'-0\". Read it together with `real`; only the ratio real ÷ drawing matters."
},
"real": {
"type": "number",
"exclusiveMinimum": 0.0,
"title": "Real",
"description": "The real-world length that `drawing` stands for: the 50 in \"1:50\". The scale factor is real ÷ drawing, e.g. 50 for 1:50, or 48 for 1/4\" = 1'-0\"."
},
"label": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Label",
"description": "The scale as printed on the sheet or entered by a person, e.g. \"1:50\" or 1/4\" = 1'-0\". It can be `null`; the ratio is always in `drawing` and `real`."
},
"type": {
"$ref": "#/$defs/ScaleType",
"description": "The family of the scale. It sets how the Kamai app displays values: `metric` shows metres and m², every other type feet and square feet; door and window widths show in centimetres when the type is `metric` or the units are `si`. It does not change the API: `measurements` are always SI (m, m²)."
},
"units": {
"$ref": "#/$defs/ScaleUnits",
"description": "The unit `drawing` and `real` are both expressed in. They share it, and only their ratio real ÷ drawing is used."
},
"manual_scaling_needed": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Manual Scaling Needed",
"description": "`true` when Kamai set this scale automatically and no person has confirmed it yet: either the scale read from the sheet's title block, or a default for the detected measurement system when none could be read. Measurements use it normally. It clears when someone sets the scale in the Kamai app. A PUT stores the scale as a person's: `false` unless the body sends the flag. `false` or `null` means a person set or confirmed it, and a re-process keeps such a scale. Sending `true` marks the scale as Kamai's on purpose (unconfirmed): a re-process then recomputes it from the sheet."
}
},
"type": "object",
"required": [
"drawing",
"real",
"type",
"units"
],
"title": "BlueprintScalePublic",
"description": "The sheet's drawing scale: real length = drawing length × real ÷ drawing."
},
"BlueprintTextPublic": {
"properties": {
"id": {
"type": "string",
"title": "Id",
"description": "Stable id for this word"
},
"text": {
"type": "string",
"title": "Text",
"description": "The word itself"
},
"confidence": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"title": "Confidence",
"description": "0..1. The OCR score for a recognised word; 1.0 for text read out of the PDF's own digital layer."
},
"geometry": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"title": "Geometry",
"description": "The word's box in blueprint coordinates, as GeoJSON. Follows the true (possibly rotated) glyph run, not an upright box."
},
"room_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Room Id",
"description": "The room this word is printed in, if any."
},
"wall_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Wall Id",
"description": "The wall this word is printed on, if any."
}
},
"type": "object",
"required": [
"id",
"text"
],
"title": "BlueprintTextPublic",
"description": "One word read off the sheet.\n\nSeparate from `features` on purpose: text is not part of the legend/folder\ntree — it has no folder, no position and no place in the hierarchy — and a\nsheet carries thousands of words against a few hundred real features."
},
"FeatureClass": {
"type": "string",
"enum": [
"room",
"wall",
"wall_centerline",
"wall_surface",
"wall_surface_with_opening",
"opening",
"footprint",
"other"
],
"title": "FeatureClass"
},
"FeatureColorPublic": {
"properties": {
"r": {
"type": "integer",
"maximum": 255.0,
"minimum": 0.0,
"title": "R"
},
"g": {
"type": "integer",
"maximum": 255.0,
"minimum": 0.0,
"title": "G"
},
"b": {
"type": "integer",
"maximum": 255.0,
"minimum": 0.0,
"title": "B"
},
"a": {
"type": "integer",
"maximum": 255.0,
"minimum": 0.0,
"title": "A"
}
},
"type": "object",
"required": [
"r",
"g",
"b",
"a"
],
"title": "FeatureColorPublic",
"description": "Display colour, 0-255 per channel."
},
"FeatureKind": {
"type": "string",
"enum": [
"area",
"line",
"object",
"text",
"folder"
],
"title": "FeatureKind"
},
"FeatureMeasurementsPublic": {
"properties": {
"area_m2": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"title": "Area M2",
"description": "Polygon area, m²."
},
"perimeter_m": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"title": "Perimeter M",
"description": "Polygon boundary length, m (holes included)."
},
"length_m": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"title": "Length M",
"description": "Line length, m."
},
"opening_width_m": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"title": "Opening Width M",
"description": "Door/window clear width, m. Converted from `opening_width_units`."
},
"wall_thickness_m": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"title": "Wall Thickness M",
"description": "Walls only: thickness face to face as drawn, m. Converted from `wall_thickness_units`. `null` on every other class and on a wall whose thickness was not measured."
}
},
"type": "object",
"title": "FeatureMeasurementsPublic",
"description": "Real-world measurements the server derives from the geometry and the sheet's scale,\nalways in SI units (m, m²); each field's unit is in its name. Read-only: ignored on a PUT.\n\n``null`` means *not applicable or not measurable*, never a measured zero: a line has no\narea, a folder has no geometry, and a sheet without a usable scale has no measurements\nat all. They follow the GEOMETRY, not ``kind``: an object drawn as a polygon carries an\n``area_m2``. Objects are counted, not measured, so do not sum them into a room total."
},
"FeatureSubClass": {
"type": "string",
"enum": [
"window",
"swing window",
"safe room window",
"single swing door",
"double swing door",
"sliding door",
"toilet",
"sink",
"bathtub",
"shower",
"cooktop",
"stairs",
"elevator",
"wet room",
"wet wall"
],
"title": "FeatureSubClass"
},
"ScaleType": {
"type": "string",
"enum": [
"architectural",
"metric",
"civil",
"custom"
],
"title": "ScaleType"
},
"ScaleUnits": {
"type": "string",
"enum": [
"si",
"imperial",
"inches"
],
"title": "ScaleUnits"
},
"SheetIdentityPublic": {
"properties": {
"sheet_number": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Sheet Number",
"description": "The sheet number as printed in the title block, e.g. A-101. Not unique within a project."
},
"title": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Title",
"description": "The sheet title as printed, e.g. FIRST FLOOR PLAN."
},
"discipline": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Discipline",
"description": "Discipline letter of the US National CAD Standard, e.g. A (architectural), S (structural), M (mechanical)."
},
"sheet_type": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Sheet Type",
"description": "Sheet-type digit of the US National CAD Standard, 0-9, e.g. 1 for plans."
},
"sheet_type_label": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Sheet Type Label",
"description": "The sheet type's name, e.g. Plans."
},
"levels": {
"items": {
"type": "string"
},
"type": "array",
"title": "Levels",
"description": "Every building level the title names, e.g. [\"L1\", \"L2\"]; empty when it names none."
}
},
"type": "object",
"title": "SheetIdentityPublic",
"description": "What the sheet's title block says it is."
}
}
}
Work with this as data
Every JSON Schema here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for schemas
4 MCP tools reach this
find_json_schemasBrowse and filter every JSON Schema in the catalog.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.
Call it yourself
curl for this page
This JSON Schema
curl "https://apis.io/api/v1/json-schemas/kamai-io-blueprint-details-response"
All schemas
curl "https://apis.io/api/v1/json-schemas?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.