space-ocr-com · Schema

OcrMarkdownResponse

OCRAIDocument-ProcessingField-ExtractionAPI

Properties

Name Type Description
status string
data object
message string
View JSON Schema on GitHub

JSON Schema

space-ocr-com-ocr-markdown-response-schema.json Raw ↑
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/space-ocr-com/json-schema/space-ocr-com-ocr-markdown-response-schema.json",
  "title": "OcrMarkdownResponse",
  "x-generated": "2026-10-31",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/space-ocr-com-openapi.json#/components/schemas/OcrMarkdownResponse",
  "type": "object",
  "properties": {
    "status": {
      "type": "string"
    },
    "data": {
      "type": "object",
      "properties": {
        "values": {
          "type": "object",
          "properties": {
            "markdown": {
              "type": "string",
              "description": "The assembled Markdown string."
            },
            "elements": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/MarkdownElement"
              },
              "description": "Content-only elements (default; omitted when includeElements: false) — coordinates and verification flags live in cells. OCR tokens no element claimed are recovered as a trailing paragraph (evidence.source: unclaimed_tokens)."
            }
          },
          "required": [
            "markdown"
          ]
        },
        "cells": {
          "type": "object",
          "additionalProperties": {
            "$ref": "#/$defs/Cell"
          },
          "description": "Path-keyed map — elements[3] is an element, elements[2].cells[1] a table cell. Omitted when includeElements: false."
        },
        "review": {
          "$ref": "#/$defs/Review"
        },
        "image": {
          "$ref": "#/$defs/ImageInfo"
        }
      },
      "required": [
        "values",
        "review",
        "image"
      ]
    },
    "message": {
      "type": "string"
    }
  },
  "required": [
    "status",
    "data"
  ],
  "$defs": {
    "Cell": {
      "type": "object",
      "properties": {
        "box": {
          "type": "object",
          "properties": {
            "xmin": {
              "type": "number"
            },
            "ymin": {
              "type": "number"
            },
            "xmax": {
              "type": "number"
            },
            "ymax": {
              "type": "number"
            }
          },
          "required": [
            "xmin",
            "ymin",
            "xmax",
            "ymax"
          ],
          "description": "Axis-aligned rectangle, normalized to 0–1000 — convert to pixels with data.image (pixel_x = xmin / 1000 × width)."
        },
        "quad": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "x": {
                "type": "number"
              },
              "y": {
                "type": "number"
              }
            },
            "required": [
              "x",
              "y"
            ]
          },
          "description": "Four corners following a tilted scan — always present alongside box, same 0–1000 frame (the page as read; see data.image). No deskew is applied: coordinates stay in the input image's coordinate system."
        },
        "verified": {
          "type": [
            "boolean",
            "null"
          ],
          "description": "The cell's verdict — a mirror of review (engine v82): false whenever review carries reasons (any kind, declared rules included), true when nothing was flagged and a check actually ran, null when nothing was flagged but there was nothing to check (geometry-only units such as row unions and table containers). The character cross-check itself lives at evidence.text_match."
        },
        "review": {
          "type": [
            "object",
            "null"
          ],
          "properties": {
            "reasons": {
              "type": "array",
              "items": {
                "type": "string"
              },
              "description": "Every rule broken, ordered by rank — index 0 is the primary verdict (always an array, even at length one). Vocabulary: \"type_mismatch\" | \"out_of_range\" | \"pattern_mismatch\" | \"near_mismatch\" | \"near_ambiguous\" | \"near_conflict\" (the first six are rules the caller declared, ranked above engine-inferred reasons) | \"nobox\" | \"text_mismatch\" | \"crop_mismatch\" | \"low_ratio\" | \"weak_source\" | \"low_ocr_confidence\" | \"ambiguous_occurrence\" | \"overwide_box\" | \"missing\". New codes may be added later — fall back to a generic \"needs review\" for unknown ones."
            }
          },
          "required": [
            "reasons"
          ],
          "description": "null = passed. Anything else = human review recommended; reasons carries the ranked verdicts."
        },
        "evidence": {
          "$ref": "#/$defs/CellEvidence"
        },
        "normalized": {
          "$ref": "#/$defs/CellNormalized"
        }
      },
      "required": [
        "box",
        "quad",
        "verified",
        "review"
      ],
      "description": "One entry of the flat, path-keyed coordinate/verification map. Keys share the grammar of review.flagged[].path (items[0].price); a row path like items[0] is the row's union box. Fields that came back without coordinates (nobox) or never came back (missing) have NO cell — they appear only in review.flagged."
    },
    "CellEvidence": {
      "type": "object",
      "properties": {
        "text_match": {
          "type": "boolean",
          "description": "The character cross-check itself: did the value equal the OCR text under these coordinates (two independent engines agreeing)? Key present only when the check ran — when it could not run, verified is null. Engine v82 moved this out of `verified`, which is now the review verdict; `verified: false` with `text_match: true` is a normal combination (the characters matched and a declared rule caught it)."
        },
        "source": {
          "type": "string",
          "description": "Where the coordinates came from. Vocabulary varies by endpoint: vision_symbol_match / token_id / char_matcher_fallback / unclaimed_tokens / vision_paragraph …"
        },
        "match_ratio": {
          "type": "number",
          "description": "Match ratio of the character cross-check."
        },
        "printed_text": {
          "type": "string",
          "description": "What the OCR pass itself read at these coordinates (engine v83; /ocr/fields only). `values` is the model's rendering and the cross-check folds width / brackets / whitespace before comparing, so a value the model re-spelled still passes — use printed_text when you need an exact string match, such as reconciling against a master table. It does not supersede values (the OCR pass has its own misreads, which is why the two are cross-checked). Glyphs only — inter-word spacing is not reconstructed, so compare ignoring whitespace. Absent when nothing was matched (no box)."
        },
        "ocr_confidence": {
          "type": "number",
          "description": "Minimum OCR self-confidence over the matched glyphs. Key absent when unavailable. Not a review threshold and not declarable — gate on it caller-side if you need one."
        },
        "crop_verified": {
          "type": "boolean",
          "description": "Result of the crop re-read, present only when it ran."
        },
        "multiline": {
          "type": "boolean",
          "description": "Present (true) only when the value wraps and box is the union of those lines."
        },
        "near": {
          "type": "object",
          "properties": {
            "occurrences": {
              "type": "integer",
              "description": "How many times this value is printed on the page."
            },
            "satisfied": {
              "type": "integer",
              "description": "How many of those sit beside a declared term."
            },
            "anchored": {
              "type": "boolean",
              "description": "Whether the copy that got the coordinates is one of them."
            },
            "nearest_term": {
              "type": [
                "string",
                "null"
              ]
            },
            "nearest": {
              "type": [
                "number",
                "null"
              ],
              "description": "Gap to the closest declared term in multiples of the ALLOWED window — <= 1 would have passed (the window is anisotropic, 6 wide × 3 tall, so one absolute distance cannot be compared to one threshold)."
            }
          },
          "required": [
            "occurrences",
            "satisfied",
            "anchored"
          ],
          "description": "Present only when a field that declared `near` was flagged near_mismatch / near_ambiguous — the arithmetic of the verdict, so a reviewer can re-derive it instead of trusting the reason."
        },
        "not_near": {
          "type": "object",
          "properties": {
            "matched": {
              "type": "string"
            },
            "distance": {
              "type": "number"
            }
          },
          "required": [
            "matched",
            "distance"
          ],
          "description": "Present only on near_conflict — the declared term the value sat beside, distance in window multiples."
        }
      }
    },
    "CellNormalized": {
      "type": "object",
      "properties": {
        "value": {
          "description": "The parsed reading, or null when the printed text would not parse (see error)."
        },
        "type": {
          "type": "string"
        },
        "method": {
          "type": "string"
        },
        "error": {
          "type": "string",
          "description": "Present when value is null — why the printed text would not parse: \"not_numeric\" | \"not_an_integer\" | \"not_a_date\" | \"no_year\" | \"conventional_token\" (a legitimate printed convention such as 一式 — read correctly, just not the declared type) | \"relative_date\"."
        }
      },
      "required": [
        "type"
      ],
      "description": "Deterministic second reading of the value in the declared scalar type. Present only on /ocr/fields cells whose field declared number / integer / date (or a string carrying pattern / enum)."
    },
    "FlaggedEntry": {
      "type": "object",
      "properties": {
        "path": {
          "type": "string",
          "description": "Same grammar as the cells map keys — a direct lookup. Note: missing is raised only for fields declared required; an undeclared field that never comes back raises no flag."
        },
        "reasons": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Every rule broken, ordered by rank — index 0 is the primary verdict (always an array, even at length one). Vocabulary: \"type_mismatch\" | \"out_of_range\" | \"pattern_mismatch\" | \"near_mismatch\" | \"near_ambiguous\" | \"near_conflict\" (the first six are rules the caller declared, ranked above engine-inferred reasons) | \"nobox\" | \"text_mismatch\" | \"crop_mismatch\" | \"low_ratio\" | \"weak_source\" | \"low_ocr_confidence\" | \"ambiguous_occurrence\" | \"overwide_box\" | \"missing\". New codes may be added later — fall back to a generic \"needs review\" for unknown ones."
        }
      },
      "required": [
        "path",
        "reasons"
      ]
    },
    "ImageInfo": {
      "type": "object",
      "properties": {
        "width": {
          "type": "integer"
        },
        "height": {
          "type": "integer"
        }
      },
      "required": [
        "width",
        "height"
      ],
      "description": "The size in pixels of the page as read — the frame every coordinate lives in (pixel_x = xmin / 1000 × width). Measured after the page is turned upright (EXIF) and after any downscale, so it can differ from the file you sent: a sideways 4000×3000 photo can come back 3000×4000."
    },
    "MarkdownElement": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "description": "\"heading\" | \"paragraph\" | \"list_item\" | \"blockquote\" | \"code_block\" | \"thematic_break\" | \"table\"."
        },
        "text": {
          "type": "string",
          "description": "The element's text (all kinds except table)."
        },
        "level": {
          "type": "integer",
          "description": "Heading level (heading only)."
        },
        "rows": {
          "type": "integer",
          "description": "Row count (table only)."
        },
        "cols": {
          "type": "integer",
          "description": "Column count (table only)."
        },
        "cells": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "row": {
                "type": "integer"
              },
              "col": {
                "type": "integer"
              },
              "header": {
                "type": "boolean"
              },
              "text": {
                "type": "string"
              }
            },
            "required": [
              "row",
              "col",
              "text"
            ]
          },
          "description": "The table's cells (table only)."
        }
      },
      "required": [
        "type"
      ]
    },
    "Review": {
      "type": "object",
      "properties": {
        "unit": {
          "type": "string",
          "description": "\"field\" on /ocr/fields, \"element\" on /ocr/markdown, \"block\" on /ocr/text."
        },
        "declared": {
          "type": "integer",
          "description": "/ocr/fields only — every declared slot, empty and unreturned required included (a fixed denominator)."
        },
        "returned": {
          "type": "integer",
          "description": "/ocr/fields only — non-empty values."
        },
        "total": {
          "type": "integer",
          "description": "/ocr/markdown and /ocr/text — total counted units (each table cell counts on its own)."
        },
        "boxed": {
          "type": "integer",
          "description": "Units that carry a box."
        },
        "verified": {
          "type": "integer",
          "description": "Units with verified: true — nothing flagged and a check actually ran. Flagged units are not counted here; their count is flagged.length."
        },
        "flagged": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/FlaggedEntry"
          },
          "description": "The review list — the review count IS its length (no separate counter)."
        },
        "by_reason": {
          "type": "object",
          "additionalProperties": {
            "type": "integer"
          },
          "description": "Per-reason tally. One cell can break a declared rule AND carry an engine suspicion, so every entry in reasons is counted — the total is therefore at least flagged.length."
        },
        "coverage": {
          "type": "object",
          "properties": {
            "recovered_blocks": {
              "type": "number"
            },
            "vision_tokens": {
              "type": "number"
            },
            "tokens_claimed": {
              "type": "number"
            },
            "token_coverage": {
              "type": "number"
            }
          },
          "description": "How much of the page came back (document endpoints; LLM path only on /ocr/text)."
        },
        "notes": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/ReviewNote"
          },
          "description": "Present only when a declaration did not run as written — branch on issue."
        }
      },
      "required": [
        "unit",
        "boxed",
        "verified",
        "flagged",
        "by_reason"
      ]
    },
    "ReviewNote": {
      "type": "object",
      "properties": {
        "path": {
          "type": "string"
        },
        "issue": {
          "type": "string",
          "description": "What did not run as declared: \"type_coerced\" (unsupported declared type read as string; declared_type / applied_type ride along) | \"label_unresolved\" (a declared label anchored nothing — the value still comes back, so this note is the only trace that the declaration is inert) | \"near_unresolved\" (no declared near term is printed anywhere — the check abstained)."
        },
        "description": {
          "type": "string"
        }
      },
      "required": [
        "path",
        "issue"
      ]
    }
  }
}

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.
All 92 tools →

Call it yourself

curl for this page
This JSON Schema
curl "https://apis.io/api/v1/json-schemas/space-ocr-com-ocr-markdown-response"
All schemas
curl "https://apis.io/api/v1/json-schemas?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

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.