machinewitness

Machine access

Ask the archive from software

This archive records what the web tells machines. It would be a strange archive if only a human filling in a form could question it. Two operations are open to software: ask whether a domain is observed, and suggest one for observation. No key, no registration, no account.

Both operations return metadata only. Neither one returns the contents of any observed file, and there is no endpoint that lists or searches the observed set. What a file said on a given day is part of an evidence extract, issued on request; see evidence extract.

Since October 2026 software can also order a point-in-time record; it prepares a payment, nothing more. See ordering a point-in-time record.

For an assistant: the MCP server

If you use Claude, ChatGPT, or anything else that speaks the Model Context Protocol, add this endpoint and the two tools appear in your conversation.

https://machinewitness.eu/mcp

It uses the Streamable HTTP transport and is stateless: no session to establish, no stream held open, no credentials. Add it as a remote MCP server in your client's settings, or from the command line:

claude mcp add --transport http machinewitness https://machinewitness.eu/mcp

check_coverage

check_coverage(domain)

Whether this archive observes a domain, from which sealed day onward, which machine-readable files it requests, and how often. A pasted URL is accepted and reduced to the domain name.

A negative answer is a statement about this archive, not about the domain: most of the web is not observed. A positive answer says nothing about what the observed files contain.

suggest_domain

suggest_domain(domain, email, reason)

Suggest that a domain be observed. The answer is always received with guarantee: none. It is a request, not an instruction. See what suggesting does and does not do below.

For everything else: plain HTTP

The same two operations without MCP, and the root log as one document. Nothing here needs a library.

The whole root log

GET /log.json

Every sealed day, both witnesses, in one document: the number of observations, the Merkle root, the exact seal time, and which external anchors that day carries. It is the machine-readable form of the public log: no key, no pagination, no rate limit.

$ curl -s https://machinewitness.eu/log.json | jq '.days[0]'
{
  "day": "2026-08-23",
  "url": "https://machinewitness.eu/log/2026-08-23",
  "witnesses": {
    "witness-1": {
      "sealed": true,
      "observations": 645785,
      "merkle_root": "a86d011c...",
      "anchors": {"opentimestamps": true, "rfc3161": true, "qualified_eidas": true}
    },
    "witness-2": { "sealed": true, "observations": 608542, "merkle_root": "eb3e7e97..." }
  }
}

The two witnesses seal independently, so their roots differ by construction and are never presented as matching. A witness with no seal for a day says so explicitly ("sealed": false with a reason) rather than being left out. An absent line must never read as "not applicable". This document states what was sealed, never what any domain served.

Is a domain observed?

GET /coverage/{sha256(domain)}

The key is the lowercase hexadecimal SHA-256 of the bare domain name: no scheme, no www., no trailing dot. You hash the name yourself, so it is never transmitted and never appears in a log. That is deliberate: a neutral witness should not accumulate a record of who asked about whom.

$ printf 'example.eu' | shasum -a 256
5a9f...  -

$ curl https://machinewitness.eu/coverage/5a9f...
{"observed": false}

An observed domain answers with the sealed dates, the artefacts requested, and the ring that determines cadence:

{
  "observed": true,
  "first_sealed_observation": "2026-07-29",
  "last_sealed_observation": "2026-08-02",
  "artefacts": ["robots.txt", "ai.txt", "tdmrep.json", "llms.txt", "homepage"],
  "ring": "core",
  "active": true
}

A domain that is no longer observed answers "active": false. Its sealed records from the period shown remain. An archive does not un-observe the past.

Suggest a domain

POST /request

$ curl -X POST https://machinewitness.eu/request \
    -H 'content-type: application/json' \
    -d '{"domain": "example.eu",
         "email": "you@example.eu",
         "reason": "Why this domain should be observed."}'

{"status": "received",
 "guarantee": "none",
 "domain": "example.eu",
 "detail": "Recorded for review against documented criteria. ..."}

All three fields are required. A rejected suggestion answers "status": "rejected" with a reason: an unusable domain name, a missing reply address, or a reason too short to be read as one.

Ordering a point-in-time record

Software can also order a point-in-time record: both witnesses fetch the addresses you name, take a full-page picture of each, and give each capture its own qualified electronic time-stamp. Ordering this way prepares a payment and nothing else. The answer is a payment link; nothing is charged and nothing is captured until a person has paid on that page. The record is delivered by e-mail, usually within minutes; after the night's seal a second e-mail follows with the day seal. Fees: services and fees.

Before the link is created, every address is checked at no charge: a public domain name, not on the stop list, robots.txt allows our crawler, and it answers without a login. An address that fails is named with the reason, and no link is created. Only addresses are asked for, never a purpose or a matter.

order_capture · POST /order/capture

order_capture(addresses, language, email, timezone)

$ curl -X POST https://machinewitness.eu/order/capture \
    -H 'content-type: application/json' \
    -d '{"addresses": ["https://example.eu/terms"],
         "language": "en",
         "email": "you@example.eu",
         "timezone": "Europe/Berlin"}'

{"status": "ok",
 "reference": "MW-K-3F9A2C1D",
 "checkout_url": "https://checkout.stripe.com/...",
 "expected_start": "2026-10-02T09:02:00.000Z",
 "delivery_notice": "...",
 "status_url": "https://machinewitness.eu/order/capture/MW-K-3F9A2C1D"}

{"status": "precheck_failed",
 "refused": [{"address": "https://example.eu/account",
              "reason": "login", "detail": "This address asks for a login."}],
 "detail": "..."}

Up to twenty addresses on one domain. language is one of en, de, es, fr, it, pl and sets the payment page and the e-mails; email prefills the payment page; timezone (IANA, for example Europe/Berlin, default Europe/Madrid) is the zone in which delivery_notice states the time. expected_start is the start promised before payment (UTC): now if the witnesses are free, otherwise the end of their daily work plus a margin; null if they gave no estimate. No capture starts after 21:30 UTC; a later order starts in the first free window of the next day.

capture_status · GET /order/capture/{reference}

capture_status(reference)

$ curl https://machinewitness.eu/order/capture/MW-K-3F9A2C1D

{"reference": "MW-K-3F9A2C1D",
 "status": "first_delivery_sent",
 "addresses": 1,
 "capture_day": "2026-10-02",
 "witnesses": {"witness-1": "captured", "witness-2": "captured"},
 "first_delivery_at": "2026-10-02T09:14:03Z",
 "complete_delivery_at": null}

Where an order stands, overall and per witness: awaiting payment, queued, capturing, first delivery sent, complete. It never returns the e-mail address, the addresses ordered or anything else about the customer.

Ordering an evidence extract or an observation

Two further MCP tools prepare a payment in the same way, for the evidence extract and for the daily observation. They exist on the MCP endpoint only. The answer is a payment link; nothing is charged, and nothing starts, until a person has paid on that page. Fees: services and fees.

order_extract · MCP

order_extract(domains, language, email)

Everything this archive recorded on a domain, as one verifiable document. One to twenty domains. A domain this archive never observed is refused by name before the link is created, because there would be nothing to deliver; ask check_coverage first. The extract is normally delivered by e-mail within five working days of payment.

order_observation · MCP

order_observation(domains, interval, language, email)

Daily observation as a yearly or monthly subscription (interval year or month, default year), one to 500 domains. A domain already observed daily in the core is refused by name, because it costs nothing. Subpages are added on the order page, not through the tool. Admission within five working days of payment, entered in the public record.

What suggesting does, and what it does not

A suggestion is recorded and reviewed by a person against documented criteria: a connection to the European Union, and publicly served machine-readable files. The decision stays with the operator of this archive.

It creates no obligation to observe the domain, no timeline, and no assurance that it will be added. That is not legal decoration, it is the honest position. An archive that promised to observe on request would owe an availability it cannot guarantee, and the person who relied on that promise would find the evidence missing on the day a crawl failed. What is promised here is smaller and can be kept: the suggestion is recorded, it is reviewed, and it is answered at the address given.

The domain's ending is one signal among others, not a verdict. A domain outside the 28 European endings is not rejected automatically. It is put in front of a person, because an ending is a rough proxy for where an operator actually is. That limitation is described on how it works.

Limits and conduct

Rate limits
Suggestions are limited per address and in total per day. Exceeding a limit answers 429. The coverage lookup is cached at the edge and is not rate limited for ordinary use.
Enumeration
There is no endpoint that lists observed domains, and the hashed key means the lookup cannot be walked. Each lookup answers for one domain the caller already knows.
Personal data
The coverage lookup transmits no domain name and no personal data. A suggestion sends the domain and your address in the clear. It has to, because a person reads it. See the privacy notice.
Stability
These are the public operations of a working archive, not a versioned product API. Fields may be added; the meaning of existing fields will not be changed silently. A wider data API is a later, separate matter.

Machine-readable descriptions

This site publishes what it asks of others. llms.txt describes both access paths in a form a language model can read directly; ai.txt and tdmrep.json state that no reservation is made against text and data mining of this site's own content.

Something not working, or an answer that looks wrong? Write to contact@machinewitness.eu. Automated access that causes trouble will be limited rather than silently blocked, and you will be told.