Contrie Extract API
The Extract API from Contrie — 1 operation(s) for extract.
The Extract API from Contrie — 1 operation(s) for extract.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
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.curl "https://apis.io/api/v1/apis/contrie-com:contrie-com-extract-api"
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.
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: 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