Developers
This feature is not enabled. The existing security page, status page and checker remain available.
Build with the open checker
Bytes, a time window, and a reading you can repeat.
Start offline. No account, API key or upload is needed to check an existing stamp. A stamp does not establish that its content is true.
Check a file
npx openstamps@1.0.0-rc.1 check record.cts original.json --jsonExit 0: ◇ not refuted. Exit 1: ✕ refuted. Exit 2: ◔ not checked, with a reason. Other exits mean the command did not complete.
Node example
import { readFile } from 'node:fs/promises';
import { checkStamp } from 'openstamps';
const stamp = await readFile('record.cts');
console.log(await checkStamp({ stamp }));Hosted API and MCP stamping starts with paid Stand. Checking existing stamps and browser stamping stay free.
Timestamp API
GET /api/stamp describes version 0.1.0 and the deployment's current limits. POST /api/stamp requests authority tokens for a SHA-256 fingerprint; it does not return a completed stamp.
Create an API key under API & agents in your account. Send it in the x-osfp-key request header, never in a URL. Authenticated requests can consume allowance. Keep the key on your server. Handle 402 (balance), 429 (quota, with Retry-After) and 503 (unavailable) separately.
Not requested yet. This button reads the public contract; it creates no stamp.
Conformance pack
36 named reader cases from nine public samples: original agreement, changed original, changed core and an unsupported future version. Runs offline with Node 20+.
Download runner, vectors and report · Read report · 22 extension ids
node reference-runner.mjsReference agreement is not independent acceptance. The older independent decoder reproduces 14 of 23 extension vectors, nine with inferred assumptions; nine remain unimplemented or differ. No certification or promotion is claimed.
Tools and examples
npx openstamps@1.0.0-rc.1 mcpThis published check-only MCP runs locally over stdio and needs no API key. To stamp files or read your balance from an MCP app, use the separate downloadable server in your account setup guide; an optional API key authorizes funded requests there.
WebMCP uses tools on an open page in a compatible browser. It needs neither an API key nor that local server. Follow the browser setup steps.
Read a folder · Stamp and check · Evidence file · Sample stamp
Webhooks and versions
Existing deliveries sign the exact body with HMAC-SHA256. Header: x-openstamps-signature: t=…,v1=…. Check the timestamp within 300 seconds and compare the signature in constant time before processing. Deduplicate the event; a signature alone does not prevent replay.
Built with CSTP
A technology label only: no approval, certification or claim that an application is correct. Link it to the specification and say what your application actually checks.
Read the API contract
All five examples call the same existing, read-only endpoint: GET https://openstamps.com/api/stamp. They create no stamp and need no key.
cURL
curl --fail-with-body --max-time 10 \
https://openstamps.com/api/stampNode
const response = await fetch('https://openstamps.com/api/stamp', {
signal: AbortSignal.timeout(10000)
});
if (!response.ok) throw new Error('HTTP ' + response.status);
console.log(await response.json());Python
import json
from urllib.request import urlopen
with urlopen('https://openstamps.com/api/stamp', timeout=10) as response:
print(json.load(response))Go
package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
client := &http.Client{Timeout: 10 * time.Second}
response, err := client.Get("https://openstamps.com/api/stamp")
if err != nil { panic(err) }
defer response.Body.Close()
if response.StatusCode != 200 { panic(fmt.Sprint(response.StatusCode)) }
if _, err := io.Copy(os.Stdout, response.Body); err != nil { panic(err) }
}Ruby
require 'net/http'
require 'json'
uri = URI('https://openstamps.com/api/stamp')
response = Net::HTTP.start(uri.host, uri.port,
use_ssl: true, open_timeout: 10, read_timeout: 10) do |http|
http.get(uri.request_uri)
end
raise "HTTP #{response.code}" unless response.is_a?(Net::HTTPSuccess)
puts JSON.parse(response.body)Join an API waitlist
The Partner API and hosted Phoenix API are being planned. This records your interest for review; it is not an account, reservation, price or launch promise.