Contrie Extract API

The Extract API from Contrie — 1 operation(s) for extract.

GitHub OpenAPI

Operations 1

POST /api/v1/extract Extract structured data or markdown from raw HTML #

Work with this as data

Every API 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 apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • 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 API
curl "https://apis.io/api/v1/apis/contrie-com:contrie-com-extract-api"
All apis
curl "https://apis.io/api/v1/apis?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.

OpenAPI Specification

contrie-com-extract-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Contrie Com Extract API
  version: 1.0.0
  contact:
    email: hello@contrie.com
  description: 'Operations tagged Extract across 2 of this provider''s published API definitions: contrie-com-openapi.json, contrie-com-openapi.yml. Each path carries the servers of the definition it was published in.'
servers:
- url: https://www.contrie.com
security:
- bearerAuth: []
tags:
- name: Extract
paths:
  /api/v1/extract:
    post:
      operationId: extract
      summary: Extract structured data or markdown from raw HTML
      description: Request structured data or readable markdown from supplied HTML. The supplied URL labels caller-provided content and does not authenticate its origin.
      security:
      - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ExtractRequest'
      responses:
        '200':
          description: Extraction result
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExtractionResponse'
            application/x-ndjson:
              schema:
                type: string
                description: 'Newline-delimited JSON, always HTTP 200. Trace lines { event: ''trace'', stage: ''loading'' | ''processing'', detail } report progress; no ''complete'' trace line is sent. Exactly one final line follows: { event: ''result'', status, ...ExtractionResponse }, where status is the HTTP status the JSON call would have returned and success can be false, or { event: ''error'', status, success: false, error: { code, message } } when the request fails without a result after the stream started. Remove event and status before verifying a result line''s evidence. Errors before the stream starts (auth, validation, fetch) are normal JSON errors.'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: 'RATE_LIMITED (the account''s per-minute limit by plan: Free 10, Builder 30, Pro 100 requests per minute; or about 20 failed authentication attempts a minute from one client, which answers with Retry-After 60), PAGE_LIMIT_REACHED (credits unavailable) or INFERENCE_BUDGET_EXCEEDED (a processing limit). Retry-After is present only when waiting helps.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds until the caller may retry
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Extraction failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: Service unavailable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: Idempotency key conflict, expired retained response, active request, or terminal unknown outcome after abandoned work expires. IDEMPOTENCY_OUTCOME_UNKNOWN has no Retry-After and never starts more work with that key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: 'Result not accepted (RESULT_NOT_ACCEPTED: the full ExtractionResponse with success false, data null and error) or render required'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: OAuth token lacks the required Contrie account scope. See WWW-Authenticate for the required scope.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      parameters:
      - name: Idempotency-Key
        in: header
        required: false
        schema:
          type: string
          minLength: 8
          maxLength: 200
          pattern: ^[\x21-\x7E]+$
        description: Authenticated JSON requests only. Binds account, operation and request inputs; identical retries replay the encrypted response for 24 hours without new work or credits. Not supported with NDJSON streaming.
      tags:
      - Extract
    servers:
    - url: https://www.contrie.com
components:
  schemas:
    JsonSchemaSubset:
      type: object
      description: 'JSON Schema subset. type accepts one supported type or an array of supported types for nullable unions. Supported keywords: properties, required, items, enum, description. Other keywords, such as value constraints (minLength, pattern), and combinators the subset cannot express are carried unchecked. A local $ref is inlined and a nullable anyOf or oneOf becomes a type list. Only unusable schemas are refused: required that is neither a list nor a name, enum that is not a list, or a null property schema, is a 400 INVALID_REQUEST naming the keyword. Maximum 10,000 bytes when serialized as UTF-8 JSON.'
      properties:
        type:
          oneOf:
          - type: string
            enum:
            - object
            - array
            - string
            - number
            - integer
            - boolean
            - 'null'
          - type: array
            items:
              type: string
              enum:
              - object
              - array
              - string
              - number
              - integer
              - boolean
              - 'null'
            minItems: 1
            uniqueItems: true
        properties:
          type: object
        required:
          type: array
          items:
            type: string
        items:
          type: object
        enum:
          type: array
        description:
          type: string
    ExtractRequest:
      type: object
      description: Unknown fields are refused with 400 INVALID_REQUEST naming them.
      additionalProperties: false
      required:
      - html
      properties:
        html:
          type: string
          maxLength: 5000000
          description: Raw page HTML, up to 5,000,000 UTF-8 bytes. The whole request body must also stay under the hosting platform's 4.5 MB limit, above which a plain-text HTTP 413 is returned before Contrie reads it; in practice keep html under about 4.5 MB.
        url:
          type: string
          format: uri
          description: Used for context and resolving relative links; no fetch is performed.
        extract:
          type: string
          description: Natural-language description of the data to extract.
          maxLength: 4000
        schema:
          $ref: '#/components/schemas/JsonSchemaSubset'
        format:
          type: string
          enum:
          - json
          - markdown
          - both
          default: json
    ExtractionResponse:
      type: object
      required:
      - success
      - metadata
      properties:
        success:
          type: boolean
          description: The acceptance decision. For structured output, true already means metadata.valid is true and qualityScore is at least 70; the other metadata fields explain a refusal and scope an accepted answer, they are not a second gate.
        data:
          description: Extracted result matching the requested schema, or null.
          type:
          - object
          - array
          - string
          - number
          - boolean
          - 'null'
        markdown:
          type: string
          description: Present on an accepted result when format is 'markdown' or 'both'; a refused 'both' request returns neither data nor markdown. Contrie reads at most the first 100,000 characters of the page's markdown; metadata.evidenceCoverage.sourceTruncated is true when it cut.
        error:
          type: object
          description: 'Present when success is false (for example RESULT_NOT_ACCEPTED): the same code and message shape as ErrorResponse.'
          properties:
            code:
              type: string
            message:
              type: string
        metadata:
          type: object
          required:
          - publicContractVersion
          - url
          - qualityScore
          - latencyMs
          - credits
          - cached
          - evidenceCoverage
          properties:
            url:
              type: string
              format: uri
            qualityScore:
              type: integer
              minimum: 0
              maximum: 100
              description: Scoped indicator of structure, field coverage and text support, not a probability of truth; success requires valid plus a score of at least 70. When coverageMeasured is false (a natural-language-only request) the score is at most 80.
            coverageMeasured:
              type: boolean
              description: 'True when a JSON Schema let the requested fields be counted, so completeness measures them. False for a natural-language-only request: coverage was not measured, completeness earns half credit and qualityScore is at most 80.'
            valid:
              type: boolean
              description: 'Structured acceptance check: schema, requested fields and sanity checks, more than 30% of the fields in the answer populated (completeness above 0.3), and at least half of all returned values (nulls excluded) found in the page text, that is groundingCoverage.grounded at least half of groundingCoverage.total. Booleans and strings under three characters are never found, so an answer made mostly of them is not valid. Does not establish semantic correctness. Inspect success before consuming the result.'
            schemaValid:
              type: boolean
              description: Whether the structured result satisfies the supported supplied schema. Does not establish source completeness or semantic correctness.
            completeness:
              type: number
              minimum: 0
              maximum: 1
              description: 'Populated leaf fraction, measured against declared fields when their shape is known. Null and empty values reduce this fraction; zero and false count as populated. Acceptance requires more than 30% of the fields in the answer to be populated: this value must be above 0.3, so an answer at or below that share is refused. Without a field shape this describes returned values only, not coverage of the request.'
            requestedFields:
              type: object
              description: Coverage of declared schema fields in the returned objects and array items. Every declared property, including optional properties, must be returned for extraction acceptance. Explicit null acknowledges a field only if schema-valid. Absent when no field shape is measured. Does not verify how many array items exist in the source.
              properties:
                total:
                  type: integer
                  minimum: 1
                returned:
                  type: integer
                  minimum: 0
                missing:
                  type: array
                  items:
                    type: string
                  maxItems: 50
              required:
              - total
              - returned
              - missing
            grounding:
              type: number
              minimum: 0
              maximum: 1
              description: Fraction of checkable extracted values found in the source text. Inspect groundingCoverage for unchecked values; presence does not prove field attribution.
            latencyMs:
              type: integer
              description: Processing time in milliseconds after the source was acquired. It excludes the fetch and any browser render.
            trace:
              type: array
              items:
                $ref: '#/components/schemas/TraceEntry'
            groundingFields:
              type: array
              items:
                $ref: '#/components/schemas/FieldGrounding'
              description: Per-value grounding verdicts, ungrounded entries first, capped at 50. The grounding ratio above is computed over all checked values before the cap, so it can disagree with this array on a large extraction. Absent when nothing was checkable.
            groundingCoverage:
              allOf:
              - $ref: '#/components/schemas/GroundingCoverage'
              description: How many values the grounding ratio speaks for. Counted over every value, so unlike groundingFields it is not affected by the 50-entry cap. Present whenever page text was available, so an absent ratio cannot be read as 'verified fine'.
            binding:
              type: object
              additionalProperties: false
              required:
              - judged
              - conflicts
              - truncated
              description: Present on accepted model answers (structured or natural-language) from current deployments; absent on markdown, page-published structured data and rejected results, and on recorded samples, replays and monitor history stored before 2026-09-28. Absence means no check ran. A deterministic check of whether each judged value (numbers, ISO dates, short digit-bearing strings) belongs to its field, read against the passages about that field. A conflict means the value is on the page but those passages state a different value; treat that field as UNCONFIRMED and inspect it. Not a truth claim, and it changes neither acceptance nor credits. judged 0 means no field could be checked.
              properties:
                judged:
                  type: integer
                  minimum: 0
                  description: Fields that had passages to judge against. Only grounded values are judged; on a large answer only some of them (see truncated). Never less than the number of conflicts.
                conflicts:
                  type: array
                  description: Paths of fields whose passages state a different value. Paths only, from your own answer.
                  items:
                    type: object
                    additionalProperties: false
                    required:
                    - path
                    properties:
                      path:
                        type: string
                        description: JSONPath of the field, as in groundingFields.
                truncated:
                  type: boolean
                  description: 'Some grounded values were not judged: the answer had more values than the check covers, or the check hit its work cap. A field without a conflict is then not thereby confirmed.'
            credits:
              type: integer
              description: 'Customer credits charged: 0 for refused structured output; 1 for accepted markdown; 1, 3, 8 or 15 for accepted structured output, plus 2 for a successful browser-rendered answer. Each plan caps credits per request including the rendering surcharge: Free 3, Builder 5, Pro 17; an answer above the cap is refused with INFERENCE_BUDGET_EXCEEDED and charges 0.'
            contentHash:
              type: string
              description: SHA-256 of the source basis. Full source text is not embedded; reproducing this hash requires the same source basis separately.
            evidence:
              type: object
              description: Optional Ed25519 v2 seal over the complete public response except metadata.evidence itself. Verify with POST /api/v1/evidence/verify or /evidence-verifier.mjs and a separately pinned public key.
              properties:
                version:
                  type: integer
                alg:
                  type: string
                  enum:
                  - Ed25519
                keyId:
                  type: string
                signedAt:
                  type: string
                  format: date-time
                packetHash:
                  type: string
                signature:
                  type: string
                covers:
                  type: array
                  items:
                    type: string
            cached:
              type: boolean
              description: True when the page bytes came from Contrie's page cache because the request allowed options.maxAge.
            fetchedAt:
              type: string
              format: date-time
              description: Original source acquisition time, preserved when reuse is allowed.
            evidenceStatus:
              type: string
              enum:
              - signed
              - unavailable
              - not_issued_for_rejected_result
              description: Whether this response carries a usable metadata.evidence seal. A successful response can report unavailable when signing is not configured.
            qualityScoreKind:
              type: string
              enum:
              - structural_and_textual
              - not_applicable
              description: Markdown is not_applicable and has a numeric quality placeholder of 0, not a grade.
            requestId:
              type: string
              description: Identifier for customer support and request correlation.
            source:
              type: object
              description: Source provenance. Supplied HTML is caller-provided; a recorded sample is historical. Fetched time does not prove publisher freshness.
              properties:
                mode:
                  type: string
                  enum:
                  - fetched
                  - provided_html
                  - recording
                url:
                  type: string
                fetchedAt:
                  type: string
                  format: date-time
                  description: Time the source acquisition completed, including fresh reads without cache consent. Reuse and recovered responses preserve their original time. This is not the publisher's modification time. Omitted when acquisition time is unknown.
                observedAt:
                  type: string
                  format: date-time
                  description: When Contrie started this run. For a keyless recording (mode recording) it is the recording time, and fetchedAt is absent.
                rawContentHash:
                  type: string
                  description: SHA-256 (hex) of the HTML Contrie processed, encoded as UTF-8. For a valid UTF-8 page with no byte-order mark, read by a plain fetch, it matches the SHA-256 of the response body; after a browser render or a legacy-encoding decode it does not. A match shows the same page, not that any field is correct.
            publicContractVersion:
              type: integer
              enum:
              - 1
            evidenceCoverage:
              type: object
              properties:
                sourceTextIncluded:
                  type: boolean
                  enum:
                  - false
                attribution:
                  type: string
                  enum:
                  - unmeasured
                sourceCompleteness:
                  type: string
                  enum:
                  - unmeasured
                sourceTruncated:
                  type: boolean
                  enum:
                  - true
                  description: Present only when the checked source is known to have been shortened. Omission does not establish full page, field attribution or list coverage.
              required:
              - sourceTextIncluded
              - attribution
              - sourceCompleteness
    TraceEntry:
      type: object
      additionalProperties: false
      required:
      - stage
      - detail
      properties:
        stage:
          type: string
          enum:
          - loading
          - processing
          - complete
        detail:
          type: string
          description: Fixed public progress label; never partial output.
    ErrorResponse:
      type: object
      required:
      - success
      - error
      properties:
        success:
          type: boolean
          enum:
          - false
        error:
          type: object
          required:
          - code
          - message
          properties:
            code:
              type: string
              enum:
              - INVALID_REQUEST
              - INVALID_URL
              - IDEMPOTENCY_CONFLICT
              - IDEMPOTENCY_EXPIRED
              - IDEMPOTENCY_OUTCOME_UNKNOWN
              - REQUEST_IN_PROGRESS
              - NOT_FOUND
              - UNAUTHORIZED
              - INSUFFICIENT_SCOPE
              - PAYMENT_REQUIRED
              - FETCH_FAILED
              - SOURCE_REFUSED
              - RENDER_REQUIRED
              - RATE_LIMITED
              - PAGE_LIMIT_REACHED
              - SERVICE_UNAVAILABLE
              - MODELS_UNAVAILABLE
              - EXTRACTION_FAILED
              - INFERENCE_BUDGET_EXCEEDED
              - INFERENCE_UNAVAILABLE
              - RESULT_NOT_ACCEPTED
            message:
              type: string
    GroundingCoverage:
      type: object
      required:
      - total
      - checkable
      - grounded
      description: How much of the data a grounding ratio speaks for.
      properties:
        total:
          type: integer
          description: Values that assert something; nulls are not counted. Acceptance requires grounded to be at least half of this.
        checkable:
          type: integer
          description: How many of those carried enough text to search for. Booleans and strings under three characters do not; numbers are checked at any length. They still count in total, as values that were not found.
        grounded:
          type: integer
          description: How many of the checkable values were found in the page.
    FieldGrounding:
      type: object
      required:
      - path
      - value
      - grounded
      properties:
        path:
          type: string
          description: JSONPath-style location of the value inside data, e.g. $.stories[0].title. Keys that are not plain identifiers use bracket notation with JSON-escaped quotes, e.g. $["price (USD)"]; array elements are always numeric, e.g. $.items[0].
        value:
          type: string
          description: The extracted value, rendered as a string.
        grounded:
          type: boolean
          description: 'Whether this value''s text was located in the page text by the presence check: strings case-insensitive, with whitespace runs collapsed and the page''s bold, italic and inline-code markers read as formatting (a value''s own * or ` must be on the page); links as the same URL; numbers by value (31.0 matches 31); an ISO date also as the page writes it in words, inside an ISO timestamp, or as a numeric date in the day/month order the page''s own dates establish; GBP, EUR and INR as their symbol beside an amount (£53.74). It shows presence, not that the text belongs to this field or entity. False means unconfirmed by this check, not disproved: a value the page presents differently can be missed.'
        excerpt:
          type: string
          description: Page text surrounding the match, roughly 45 characters either side, with case preserved and whitespace runs collapsed. Absent when grounded is false.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: Contrie API key or resource-bound OAuth access JWT
      description: API key created at https://www.contrie.com/dashboard/keys (human sign-up in a browser; there is no programmatic key issuance), or an OAuth access token from the advertised Contrie sign-in flow. OAuth needs no additional API key. Configure credentials through the client or environment, never in a URL or agent chat.
x-refined-from:
- contrie-com-openapi.json
- contrie-com-openapi.yml