Skip to content
Start hereRecipes

Start here

On this page

Recipes

A recipe is one job: the request that does it, the response a production run returned, and what to check before you use the answer.

The 10 recorded recipes run right now without an API key. Send the request exactly as printed and Contrie replays the recorded run: no fresh fetch, 0 credits. Change the URL, the prompt or the schema and it becomes a live request, which needs a key.

Recipe 01

Rank a list and keep its order

Use it for a leaderboard, a trending page or search results: anywhere position carries meaning. Asking for page order and declaring rank in the schema keeps that order explicit in the data instead of implied by the array. Each row prints three numbers and labels only the weekly one, so the schema names all three: forks gives the unlabelled second number a field of its own.

  • contrie_extract
  • POST /api/v1/scrape
  • Runs without a key
Request
curl -X POST https://www.contrie.com/api/v1/scrape \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://github.com/trending/rust?since=weekly",
    "extract": "The top 10 trending repositories this week, in page order, with total stars, forks and stars gained this week",
    "schema": {
      "type": "object",
      "required": ["repositories"],
      "properties": {
        "repositories": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "rank",
              "repository",
              "description",
              "language",
              "stars",
              "forks",
              "stars_this_week"
            ],
            "properties": {
              "rank": { "type": "integer" },
              "repository": { "type": "string" },
              "description": { "type": ["string", "null"] },
              "language": { "type": ["string", "null"] },
              "stars": { "type": "integer" },
              "forks": { "type": "integer" },
              "stars_this_week": { "type": "integer" }
            }
          }
        }
      }
    }
  }'
{
  "name": "contrie_extract",
  "arguments": {
    "url": "https://github.com/trending/rust?since=weekly",
    "extract": "The top 10 trending repositories this week, in page order, with total stars, forks and stars gained this week",
    "schema": {
      "type": "object",
      "required": ["repositories"],
      "properties": {
        "repositories": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "rank",
              "repository",
              "description",
              "language",
              "stars",
              "forks",
              "stars_this_week"
            ],
            "properties": {
              "rank": { "type": "integer" },
              "repository": { "type": "string" },
              "description": { "type": ["string", "null"] },
              "language": { "type": ["string", "null"] },
              "stars": { "type": "integer" },
              "forks": { "type": "integer" },
              "stars_this_week": { "type": "integer" }
            }
          }
        }
      }
    }
  }
}

acceptedquality 9470/70 fields60/70 in the page text1 credit

{
  "success": true,
  "data": {
    "repositories": [
      {
        "rank": 1,
        "repository": "akitaonrails/ai-memory",
        "description": "Solution for long term memory for agent coding CLIs and to facilitate handoff between different agent vendors",
        "language": "Rust",
        "stars": 8569,
        "forks": 581,
        "stars_this_week": 1110
      },
      {
        "rank": 2,
        "repository": "cloudflare/quiche",
        "description": "🥧 Savoury implementation of the QUIC transport protocol and HTTP/3",
        "language": "Rust",
        "stars": 12690,
        "forks": 1153,
        "stars_this_week": 522
      },
      {
        "rank": 3,
        "repository": "hydra-db/hydradb",
        "description": "HydraDB - fast graph database on object storage",
        "language": "Rust",
        "stars": 12287,
        "forks": 5394,
        "stars_this_week": 8467
      }
    ]
  },
  "metadata": {
    "valid": true,
    "schemaValid": true,
    "qualityScore": 94,
    "requestedFields": { "total": 70, "returned": 70, "missing": [] },
    "groundingCoverage": { "total": 70, "checkable": 70, "grounded": 60 },
    "credits": 1
  }
}

A real production response, trimmed for the page: data shows the first 3 of 10 items, and metadata shows the fields to branch on. The full response also carries groundingFields, source and trace. Run it yourself and the replay reports credits: 0 and source.mode: "recording".

Recipe 02

Read a ranked table and keep each value with its row

Use it for reference tables that carry several numbers per row. Declaring the row as an object keeps a height, a floor count and a year attached to the building they describe.

  • contrie_extract
  • POST /api/v1/scrape
  • Runs without a key
Request
curl -X POST https://www.contrie.com/api/v1/scrape \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://en.wikipedia.org/wiki/List_of_tallest_buildings",
    "extract": "The five tallest buildings in rank order, with city, country, height in metres, floors and year completed",
    "schema": {
      "type": "object",
      "required": ["buildings"],
      "properties": {
        "buildings": {
          "type": "array",
          "items": {
            "type": "object",
            "required": ["rank", "name", "city", "country", "height_m", "floors", "year"],
            "properties": {
              "rank": { "type": "integer" },
              "name": { "type": "string" },
              "city": { "type": "string" },
              "country": { "type": "string" },
              "height_m": { "type": "number" },
              "floors": { "type": "integer" },
              "year": { "type": "integer" }
            }
          }
        }
      }
    }
  }'
{
  "name": "contrie_extract",
  "arguments": {
    "url": "https://en.wikipedia.org/wiki/List_of_tallest_buildings",
    "extract": "The five tallest buildings in rank order, with city, country, height in metres, floors and year completed",
    "schema": {
      "type": "object",
      "required": ["buildings"],
      "properties": {
        "buildings": {
          "type": "array",
          "items": {
            "type": "object",
            "required": ["rank", "name", "city", "country", "height_m", "floors", "year"],
            "properties": {
              "rank": { "type": "integer" },
              "name": { "type": "string" },
              "city": { "type": "string" },
              "country": { "type": "string" },
              "height_m": { "type": "number" },
              "floors": { "type": "integer" },
              "year": { "type": "integer" }
            }
          }
        }
      }
    }
  }
}

acceptedquality 10035/35 fields35/35 in the page text1 credit

{
  "success": true,
  "data": {
    "buildings": [
      {
        "rank": 1,
        "name": "Burj Khalifa",
        "city": "Dubai",
        "country": "United Arab Emirates",
        "height_m": 828,
        "floors": 163,
        "year": 2010
      },
      {
        "rank": 2,
        "name": "Merdeka Maybank Tower",
        "city": "Kuala Lumpur",
        "country": "Malaysia",
        "height_m": 678.9,
        "floors": 118,
        "year": 2024
      },
      {
        "rank": 3,
        "name": "Shanghai Tower",
        "city": "Shanghai",
        "country": "China",
        "height_m": 632,
        "floors": 128,
        "year": 2015
      }
    ]
  },
  "metadata": {
    "valid": true,
    "schemaValid": true,
    "qualityScore": 100,
    "requestedFields": { "total": 35, "returned": 35, "missing": [] },
    "groundingCoverage": { "total": 35, "checkable": 35, "grounded": 35 },
    "credits": 1
  }
}

A real production response, trimmed for the page: data shows the first 3 of 5 items, and metadata shows the fields to branch on. The full response also carries groundingFields, source and trace. Run it yourself and the replay reports credits: 0 and source.mode: "recording".

Recipe 03

Cite a paper

Use it to build a reference list, or to check a citation an agent wrote. journal_reference and doi are nullable in the schema, so a preprint can say it has neither. The doi that came back is the one arXiv issued, 10.48550/arXiv.1602.03837; the journal's own DOI is on the page as the "Related DOI", so ask for that one by name when you need the publisher's.

  • contrie_extract
  • POST /api/v1/scrape
  • Runs without a key
Request
curl -X POST https://www.contrie.com/api/v1/scrape \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://arxiv.org/abs/1602.03837",
    "extract": "The citation details of this paper: title, authors, submission date, journal reference, DOI and primary subject",
    "schema": {
      "type": "object",
      "required": [
        "title",
        "authors",
        "submitted",
        "journal_reference",
        "doi",
        "primary_subject"
      ],
      "properties": {
        "title": { "type": "string" },
        "authors": { "type": "array", "items": { "type": "string" } },
        "submitted": { "type": "string" },
        "journal_reference": { "type": ["string", "null"] },
        "doi": { "type": ["string", "null"] },
        "primary_subject": { "type": "string" }
      }
    }
  }'
{
  "name": "contrie_extract",
  "arguments": {
    "url": "https://arxiv.org/abs/1602.03837",
    "extract": "The citation details of this paper: title, authors, submission date, journal reference, DOI and primary subject",
    "schema": {
      "type": "object",
      "required": [
        "title",
        "authors",
        "submitted",
        "journal_reference",
        "doi",
        "primary_subject"
      ],
      "properties": {
        "title": { "type": "string" },
        "authors": { "type": "array", "items": { "type": "string" } },
        "submitted": { "type": "string" },
        "journal_reference": { "type": ["string", "null"] },
        "doi": { "type": ["string", "null"] },
        "primary_subject": { "type": "string" }
      }
    }
  }
}

acceptedquality 1007/7 fields7/7 in the page text1 credit

{
  "success": true,
  "data": {
    "title": "Observation of Gravitational Waves from a Binary Black Hole Merger",
    "authors": ["The LIGO Scientific Collaboration", "the Virgo Collaboration"],
    "submitted": "11 Feb 2016",
    "journal_reference": "Phys. Rev. Lett. 116, 061102 (2016)",
    "doi": "10.48550/arXiv.1602.03837",
    "primary_subject": "General Relativity and Quantum Cosmology (gr-qc)"
  },
  "metadata": {
    "valid": true,
    "schemaValid": true,
    "qualityScore": 100,
    "requestedFields": { "total": 7, "returned": 7, "missing": [] },
    "groundingCoverage": { "total": 7, "checkable": 7, "grounded": 7 },
    "credits": 1
  }
}

A real production response, trimmed for the page: metadata shows the fields to branch on. The full response also carries groundingFields, source and trace. Run it yourself and the replay reports credits: 0 and source.mode: "recording".

Recipe 04

Enrich a lead from a company page

Use it to fill a CRM record or brief a sales agent from a page you already trust. Arrays in the schema keep several industries or founders as separate values instead of one joined string, so each can be checked against the page on its own.

  • contrie_extract
  • POST /api/v1/scrape
  • Runs without a key
Request
curl -X POST https://www.contrie.com/api/v1/scrape \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://en.wikipedia.org/wiki/Stripe,_Inc.",
    "extract": "The company profile from the infobox: name, industries, year founded, founders, headquarters, revenue and number of employees",
    "schema": {
      "type": "object",
      "required": [
        "name",
        "industries",
        "founded",
        "founders",
        "headquarters",
        "revenue",
        "employees"
      ],
      "properties": {
        "name": { "type": "string" },
        "industries": { "type": "array", "items": { "type": "string" } },
        "founded": { "type": "integer" },
        "founders": { "type": "array", "items": { "type": "string" } },
        "headquarters": { "type": "string" },
        "revenue": { "type": ["string", "null"] },
        "employees": { "type": ["integer", "null"] }
      }
    }
  }'
{
  "name": "contrie_extract",
  "arguments": {
    "url": "https://en.wikipedia.org/wiki/Stripe,_Inc.",
    "extract": "The company profile from the infobox: name, industries, year founded, founders, headquarters, revenue and number of employees",
    "schema": {
      "type": "object",
      "required": [
        "name",
        "industries",
        "founded",
        "founders",
        "headquarters",
        "revenue",
        "employees"
      ],
      "properties": {
        "name": { "type": "string" },
        "industries": { "type": "array", "items": { "type": "string" } },
        "founded": { "type": "integer" },
        "founders": { "type": "array", "items": { "type": "string" } },
        "headquarters": { "type": "string" },
        "revenue": { "type": ["string", "null"] },
        "employees": { "type": ["integer", "null"] }
      }
    }
  }
}

acceptedquality 1009/9 fields9/9 in the page text1 credit

{
  "success": true,
  "data": {
    "name": "Stripe, Inc.",
    "industries": ["Financial services", "Payment processor"],
    "founded": 2009,
    "founders": ["Patrick Collison", "John Collison"],
    "headquarters": "South San Francisco, California, U.S. and Dublin, Ireland",
    "revenue": "US$5.1 billion",
    "employees": 8500
  },
  "metadata": {
    "valid": true,
    "schemaValid": true,
    "qualityScore": 100,
    "requestedFields": { "total": 9, "returned": 9, "missing": [] },
    "groundingCoverage": { "total": 9, "checkable": 9, "grounded": 9 },
    "credits": 1
  }
}

A real production response, trimmed for the page: metadata shows the fields to branch on. The full response also carries groundingFields, source and trace. Run it yourself and the replay reports credits: 0 and source.mode: "recording".

Recipe 05

Read official exchange rates

Use it when a number has to be the published one: rates, tariffs, fee tables. Declaring rate as a number and asking for the date keeps a stale table from passing as today's.

  • contrie_extract
  • POST /api/v1/scrape
  • Runs without a key
Request
curl -X POST https://www.contrie.com/api/v1/scrape \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.ecb.europa.eu/stats/policy_and_exchange_rates/euro_reference_exchange_rates/html/index.en.html",
    "extract": "Every euro foreign exchange reference rate on the page, with the date they apply to",
    "schema": {
      "type": "object",
      "required": ["date", "rates"],
      "properties": {
        "date": { "type": "string" },
        "rates": {
          "type": "array",
          "items": {
            "type": "object",
            "required": ["code", "currency", "rate"],
            "properties": {
              "code": { "type": "string" },
              "currency": { "type": "string" },
              "rate": { "type": "number" }
            }
          }
        }
      }
    }
  }'
{
  "name": "contrie_extract",
  "arguments": {
    "url": "https://www.ecb.europa.eu/stats/policy_and_exchange_rates/euro_reference_exchange_rates/html/index.en.html",
    "extract": "Every euro foreign exchange reference rate on the page, with the date they apply to",
    "schema": {
      "type": "object",
      "required": ["date", "rates"],
      "properties": {
        "date": { "type": "string" },
        "rates": {
          "type": "array",
          "items": {
            "type": "object",
            "required": ["code", "currency", "rate"],
            "properties": {
              "code": { "type": "string" },
              "currency": { "type": "string" },
              "rate": { "type": "number" }
            }
          }
        }
      }
    }
  }
}

acceptedquality 10088/88 fields88/88 in the page text1 credit

{
  "success": true,
  "data": {
    "date": "18 September 2026",
    "rates": [
      { "code": "USD", "currency": "US dollar", "rate": 1.146 },
      { "code": "JPY", "currency": "Japanese yen", "rate": 180.94 },
      { "code": "CZK", "currency": "Czech koruna", "rate": 24.339 }
    ]
  },
  "metadata": {
    "valid": true,
    "schemaValid": true,
    "qualityScore": 100,
    "requestedFields": { "total": 88, "returned": 88, "missing": [] },
    "groundingCoverage": { "total": 88, "checkable": 88, "grounded": 88 },
    "credits": 1
  }
}

A real production response, trimmed for the page: data shows the first 3 of 29 items, and metadata shows the fields to branch on. The full response also carries groundingFields, source and trace. Run it yourself and the replay reports credits: 0 and source.mode: "recording".

Recipe 06

Check a package before upgrading

Use it before an agent bumps a dependency: the latest version, its release date, its license and the Python it needs, read from the package's own page.

  • contrie_extract
  • POST /api/v1/scrape
  • Runs without a key
Request
curl -X POST https://www.contrie.com/api/v1/scrape \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://pypi.org/project/requests/",
    "extract": "The package name, latest version, release date, license, required Python version and one-line summary",
    "schema": {
      "type": "object",
      "required": ["name", "version", "released", "license", "requires_python", "summary"],
      "properties": {
        "name": { "type": "string" },
        "version": { "type": "string" },
        "released": { "type": "string" },
        "license": { "type": ["string", "null"] },
        "requires_python": { "type": ["string", "null"] },
        "summary": { "type": "string" }
      }
    }
  }'
{
  "name": "contrie_extract",
  "arguments": {
    "url": "https://pypi.org/project/requests/",
    "extract": "The package name, latest version, release date, license, required Python version and one-line summary",
    "schema": {
      "type": "object",
      "required": ["name", "version", "released", "license", "requires_python", "summary"],
      "properties": {
        "name": { "type": "string" },
        "version": { "type": "string" },
        "released": { "type": "string" },
        "license": { "type": ["string", "null"] },
        "requires_python": { "type": ["string", "null"] },
        "summary": { "type": "string" }
      }
    }
  }
}

acceptedquality 1006/6 fields6/6 in the page text1 credit

{
  "success": true,
  "data": {
    "name": "requests",
    "version": "2.34.2",
    "released": "May 14, 2026",
    "license": "Apache Software License (Apache-2.0)",
    "requires_python": ">=3.10",
    "summary": "Python HTTP for Humans."
  },
  "metadata": {
    "valid": true,
    "schemaValid": true,
    "qualityScore": 100,
    "requestedFields": { "total": 6, "returned": 6, "missing": [] },
    "groundingCoverage": { "total": 6, "checkable": 6, "grounded": 6 },
    "credits": 1
  }
}

A real production response, trimmed for the page: metadata shows the fields to branch on. The full response also carries groundingFields, source and trace. Run it yourself and the replay reports credits: 0 and source.mode: "recording".

Recipe 07

Track a price and its currency

Use it for price checks, where a wrong number costs more than a missing one. The schema asks for a price and a currency, the shape most product feeds expect.

  • contrie_extract
  • POST /api/v1/scrape
  • Runs without a key
Request
curl -X POST https://www.contrie.com/api/v1/scrape \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html",
    "extract": "The product name and its current price",
    "schema": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "offers": {
          "type": "object",
          "properties": { "price": { "type": "number" }, "priceCurrency": { "type": "string" } },
          "required": ["price", "priceCurrency"],
          "additionalProperties": false
        }
      },
      "required": ["name", "offers"],
      "additionalProperties": false
    }
  }'
{
  "name": "contrie_extract",
  "arguments": {
    "url": "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html",
    "extract": "The product name and its current price",
    "schema": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "offers": {
          "type": "object",
          "properties": { "price": { "type": "number" }, "priceCurrency": { "type": "string" } },
          "required": ["price", "priceCurrency"],
          "additionalProperties": false
        }
      },
      "required": ["name", "offers"],
      "additionalProperties": false
    }
  }
}

acceptedquality 1003/3 fields3/3 in the page text1 credit

{
  "success": true,
  "data": {
    "name": "A Light in the Attic",
    "offers": { "price": 51.77, "priceCurrency": "GBP" }
  },
  "metadata": {
    "valid": true,
    "schemaValid": true,
    "qualityScore": 100,
    "requestedFields": { "total": 3, "returned": 3, "missing": [] },
    "groundingCoverage": { "total": 3, "checkable": 3, "grounded": 3 },
    "credits": 1
  }
}

A real production response, trimmed for the page: metadata shows the fields to branch on. The full response also carries groundingFields, source and trace. Run it yourself and the replay reports credits: 0 and source.mode: "recording".

Recipe 08

Read every plan off a pricing page

Use it to compare vendors or keep a cost model current. The request is plain language with no schema, which suits an answer a person or a model will read; pass a schema when code depends on the shape.

  • contrie_extract
  • POST /api/v1/scrape
  • Runs without a key
Request
curl -X POST https://www.contrie.com/api/v1/scrape \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.contrie.com/pricing",
    "extract": "Each plan with its monthly price in USD and included monthly credits"
  }'
{
  "name": "contrie_extract",
  "arguments": {
    "url": "https://www.contrie.com/pricing",
    "extract": "Each plan with its monthly price in USD and included monthly credits"
  }
}

acceptedquality 809/9 in the page text1 credit

{
  "success": true,
  "data": [
    { "plan_name": "Free", "monthly_price_usd": 0, "monthly_credits": 200 },
    { "plan_name": "Builder", "monthly_price_usd": 19, "monthly_credits": 10000 },
    { "plan_name": "Pro", "monthly_price_usd": 79, "monthly_credits": 40000 }
  ],
  "metadata": {
    "valid": true,
    "qualityScore": 80,
    "groundingCoverage": { "total": 9, "checkable": 9, "grounded": 9 },
    "credits": 1
  }
}

A real production response, trimmed for the page: metadata shows the fields to branch on. The full response also carries groundingFields, source and trace. Run it yourself and the replay reports credits: 0 and source.mode: "recording".

Recipe 09

Keep quotes with their authors

Use it for quotations, reviews or testimonials, where the words and the person who said them must stay together. One object per quote keeps text, author and tags in the same place.

  • contrie_extract
  • POST /api/v1/scrape
  • Runs without a key
Request
curl -X POST https://www.contrie.com/api/v1/scrape \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://quotes.toscrape.com/",
    "extract": "Only the first 3 quotes on the page",
    "schema": {
      "type": "object",
      "properties": {
        "quotes": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "text": { "type": "string" },
              "author": { "type": "string" },
              "tags": { "type": "array", "items": { "type": "string" } }
            },
            "required": ["text", "author", "tags"],
            "additionalProperties": false
          }
        }
      },
      "required": ["quotes"],
      "additionalProperties": false
    }
  }'
{
  "name": "contrie_extract",
  "arguments": {
    "url": "https://quotes.toscrape.com/",
    "extract": "Only the first 3 quotes on the page",
    "schema": {
      "type": "object",
      "properties": {
        "quotes": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "text": { "type": "string" },
              "author": { "type": "string" },
              "tags": { "type": "array", "items": { "type": "string" } }
            },
            "required": ["text", "author", "tags"],
            "additionalProperties": false
          }
        }
      },
      "required": ["quotes"],
      "additionalProperties": false
    }
  }
}

acceptedquality 10017/17 fields17/17 in the page text1 credit

{
  "success": true,
  "data": {
    "quotes": [
      {
        "text": "The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.",
        "author": "Albert Einstein",
        "tags": ["change", "deep-thoughts", "thinking", "world"]
      },
      {
        "text": "It is our choices, Harry, that show what we truly are, far more than our abilities.",
        "author": "J.K. Rowling",
        "tags": ["abilities", "choices"]
      },
      {
        "text": "There are only two ways to live your life. One is as though nothing is a miracle. The other is as though everything is a miracle.",
        "author": "Albert Einstein",
        "tags": ["inspirational", "life", "live", "miracle", "miracles"]
      }
    ]
  },
  "metadata": {
    "valid": true,
    "schemaValid": true,
    "qualityScore": 100,
    "requestedFields": { "total": 17, "returned": 17, "missing": [] },
    "groundingCoverage": { "total": 17, "checkable": 17, "grounded": 17 },
    "credits": 1
  }
}

A real production response, trimmed for the page: metadata shows the fields to branch on. The full response also carries groundingFields, source and trace. Run it yourself and the replay reports credits: 0 and source.mode: "recording".

Recipe 10

Read a simple page

Use it to check your client, your parsing and your branching before you point them at a page that matters.

  • contrie_extract
  • POST /api/v1/scrape
  • Runs without a key
Request
curl -X POST https://www.contrie.com/api/v1/scrape \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "extract": "Extract the page title, heading, and all paragraph text"
  }'
{
  "name": "contrie_extract",
  "arguments": {
    "url": "https://example.com",
    "extract": "Extract the page title, heading, and all paragraph text"
  }
}

acceptedquality 804/4 in the page text1 credit

{
  "success": true,
  "data": {
    "title": "Example Domain",
    "heading": "Example Domain",
    "paragraphs": [
      "This domain is for use in documentation examples without needing permission. Avoid use in operations.",
      "Learn more"
    ]
  },
  "metadata": {
    "valid": true,
    "qualityScore": 80,
    "groundingCoverage": { "total": 4, "checkable": 4, "grounded": 4 },
    "credits": 1
  }
}

A real production response, trimmed for the page: metadata shows the fields to branch on. The full response also carries groundingFields, source and trace. Run it yourself and the replay reports credits: 0 and source.mode: "recording".

Recipe 11

Read a page as markdown

format: "markdown" skips extraction entirely: 1 credit, and data is null. Its qualityScoreKind is not_applicable; the numeric placeholder 0 is not a quality grade.

  • contrie_read
  • POST /api/v1/scrape
  • Needs a key
Request
curl -X POST https://www.contrie.com/api/v1/scrape \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $CONTRIE_API_KEY" \
  -d '{ "url": "https://news.ycombinator.com", "format": "markdown" }'
{ "name": "contrie_read", "arguments": { "url": "https://news.ycombinator.com" } }

No response is printed here: this page shows only responses recorded from production, and this call has no recording. Scrape reference

Recipe 12

Verify a record you already have

Use it on data from another extractor, your own scrape or a stored record; here it is the record from the price recipe above. Verify answers one question: is this value present in this page. It bounds invention, not correctness. Verify currently charges no customer credits; only the per-account rate limit applies.

  • contrie_verify
  • POST /api/v1/verify
  • Needs a key
Request
curl -X POST https://www.contrie.com/api/v1/verify \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $CONTRIE_API_KEY" \
  -d '{
    "url": "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html",
    "data": {
      "name": "A Light in the Attic",
      "offers": { "price": 51.77, "priceCurrency": "GBP" }
    }
  }'
{
  "name": "contrie_verify",
  "arguments": {
    "url": "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html",
    "data": {
      "name": "A Light in the Attic",
      "offers": { "price": 51.77, "priceCurrency": "GBP" }
    }
  }
}

No response is printed here: this page shows only responses recorded from production, and this call has no recording. Verify reference

Recipe 13

Watch a page for changes

A monitor is a standing question about one page: here, the price recipe's question asked every 60 minutes. Contrie answers it now, answers it again on a schedule, and records a change event when the answer moves. Each run costs what one extraction costs; an unchanged page writes no event. It keeps running, and charging, until you stop it with contrie_unwatch or DELETE /api/v1/monitors/:id.

  • contrie_watch
  • POST /api/v1/monitors
  • Needs a key
Request
curl -X POST https://www.contrie.com/api/v1/monitors \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $CONTRIE_API_KEY" \
  -d '{
    "url": "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html",
    "extract": "The product name and its current price",
    "schema": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "offers": {
          "type": "object",
          "properties": { "price": { "type": "number" }, "priceCurrency": { "type": "string" } },
          "required": ["price", "priceCurrency"],
          "additionalProperties": false
        }
      },
      "required": ["name", "offers"],
      "additionalProperties": false
    },
    "every": 60,
    "webhookUrl": "https://hooks.example.com/contrie"
  }'
{
  "name": "contrie_watch",
  "arguments": {
    "url": "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html",
    "extract": "The product name and its current price",
    "schema": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "offers": {
          "type": "object",
          "properties": { "price": { "type": "number" }, "priceCurrency": { "type": "string" } },
          "required": ["price", "priceCurrency"],
          "additionalProperties": false
        }
      },
      "required": ["name", "offers"],
      "additionalProperties": false
    },
    "every": 60,
    "webhookUrl": "https://hooks.example.com/contrie"
  }
}

No response is printed here: this page shows only responses recorded from production, and this call has no recording. Monitors reference

Recipe 14

Read what changed

When a watched answer changes, the monitor records the before and after (each signed when its answer was accepted) with a diff of the fields that moved. Read the events by monitor id; the same change is sent to your webhook.

  • contrie_changes
  • GET /api/v1/monitors/:id
  • Needs a key
Request
curl https://www.contrie.com/api/v1/monitors/$MONITOR_ID \
  -H "Authorization: Bearer $CONTRIE_API_KEY"
{
  "name": "contrie_changes",
  "arguments": { "id": "<the id contrie_watch returned>" }
}

No response is printed here: this page shows only responses recorded from production, and this call has no recording. Monitors reference

Recipe 15

Branching on the response

A 200 status doesn't mean the data is good, and a caught error doesn't always mean give up. This is roughly what a production caller should do:

async function extract(url, prompt) {
  const res = await fetch("https://www.contrie.com/api/v1/scrape", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${process.env.CONTRIE_API_KEY}`,
    },
    body: JSON.stringify({ url, extract: prompt }),
  });
  const body = await res.json();

  if (!res.ok || !body.success) {
    // Refused results are not usable data. Inspect the code and Retry-After.
    return { accepted: false, error: body.error };
  }
  if (body.metadata?.qualityScoreKind !== "not_applicable") {
    // Apply your workload's acceptance criteria and inspect source evidence.
    const support = body.metadata?.grounding;
    if (support === undefined || support < 0.8) {
      return { accepted: false, needsReview: true };
    }
  }

  return body;
}