API v1

TruthStamp Developer API

Create permanent, independently verifiable on-chain proofs from any application, service, or agent — with a single HTTP request. Every stamp is recorded on MegaETH and (for public stamps) stored permanently on Arweave.

Overview

The TruthStamp API lets you timestamp content — text, URLs, or just a fingerprint — so you can later prove it existed at a specific moment. Proofs are verifiable by anyone, without trusting TruthStamp.

Base URL:

https://stlfgfaaukrgiwwkwceb.supabase.co/functions/v1/api-v1

All requests and responses are JSON. All endpoints require authentication (see below).

This is a cryptographic timestamping API. A proof shows that a hash of your content existed at a given time — it does not by itself establish authorship or legal ownership. See our disclaimer.

Authentication

Every request requires two headers:

HeaderValue
AuthorizationBearer ts_live_... — your secret API key
apikeyYour project's public anon key (required by the gateway)

Your ts_live_ key is secret — treat it like a password. The apikey value is public (it's the same anon key used by the web app) and only satisfies the platform gateway. Keys are shown once at creation and stored only as a hash; if you lose a key, revoke it and create a new one.

Keep your ts_live_ key server-side. Never embed it in client-side JavaScript, mobile apps, or public repos.

Credits

API usage draws from a dedicated API credit balance, separate from the web app's credits. Each stamp costs credits based on its type. Credits are only charged on success — if a stamp fails for any reason, your balance is automatically refunded.

Content typeCost
Text1 credit
URL2 credits
File3 credits (not in v1)

Supported stamp types

TypeStatusNotes
Public textSupportedContent stored on Arweave, publicly viewable
Sealed textSupportedHidden until a reveal date you choose
Hash-onlySupportedOnly the fingerprint is stored; content stays with you
URLSupportedURL + page snapshot recorded on Arweave
FileComing soonNot available in API v1

Create a stamp

POST /stamps

Request body

FieldTypeDescription
contentstringRequired. The text or URL to stamp.
content_typestringtext or url. Default text.
visibilitystringpublic, sealed, or hash_only. Default public.
sealed_untilnumberRequired for sealed. Unix seconds; must be ≥10 minutes in the future.
display_titlestringOptional label (shown for public/revealed stamps).
tagsstring[]Optional, up to 5 tags.

Example — public text

Request

curl -X POST "https://stlfgfaaukrgiwwkwceb.supabase.co/functions/v1/api-v1/stamps" \
  -H "Authorization: Bearer ts_live_YOUR_KEY" \
  -H "apikey: YOUR_ANON_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: a-unique-id" \
  -d '{
    "content": "My first API stamp",
    "content_type": "text",
    "visibility": "public"
  }'

Response 200

{
  "success": true,
  "proof_id": 20,
  "content_type": "text",
  "visibility": "public",
  "tx_hash": "0x996a09bf...2c3e66",
  "block_number": 18798410,
  "storage_uri": "ar://7iQwLOiVvoEq...zA8n0",
  "proof_url": "https://truthstamp.io/proof.html?id=20",
  "api_credits_remaining": 99,
  "sealed_until": null
}

Example — sealed text

Set visibility: "sealed" and a future sealed_until. The content stays hidden until that time.

curl -X POST ".../api-v1/stamps" \
  -H "Authorization: Bearer ts_live_YOUR_KEY" \
  -H "apikey: YOUR_ANON_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "BTC hits a new ATH this cycle",
    "content_type": "text",
    "visibility": "sealed",
    "sealed_until": 1781708587,
    "display_title": "BTC prediction"
  }'

Example — hash-only

Only the fingerprint is recorded on-chain. The content is never stored or transmitted to TruthStamp's storage. Useful to prove you held something without revealing it.

curl -X POST ".../api-v1/stamps" \
  -H "Authorization: Bearer ts_live_YOUR_KEY" \
  -H "apikey: YOUR_ANON_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "secret content only I know",
    "content_type": "text",
    "visibility": "hash_only"
  }'

Example — URL

curl -X POST ".../api-v1/stamps" \
  -H "Authorization: Bearer ts_live_YOUR_KEY" \
  -H "apikey: YOUR_ANON_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "https://example.com/article",
    "content_type": "url",
    "visibility": "public",
    "display_title": "Example article"
  }'

Retrieve a stamp

GET /stamps/:proof_id

Fetch the public proof data for a stamp by its proof_id. Sealed and hash-only stamps never expose their content — sealed content stays hidden until revealed, and hash-only content is never returned.

Request

curl ".../api-v1/stamps/20" \
  -H "Authorization: Bearer ts_live_YOUR_KEY" \
  -H "apikey: YOUR_ANON_KEY"

Response 200 (public stamp)

{
  "success": true,
  "proof_id": 20,
  "content_type": "text",
  "visibility": "public",
  "revealed": false,
  "content_hash": "0x34304742...bdbc1590",
  "content": "My first API stamp",
  "display_title": "My first API stamp",
  "tx_hash": "0x996a09bf...2c3e66",
  "block_timestamp": "2026-06-16T07:37:01+00:00",
  "storage_uri": "ar://7iQwLOi...zA8n0",
  "proof_url": "https://truthstamp.io/proof.html?id=20"
}

For a sealed stamp before its reveal date, or any hash-only stamp, content is returned as null and display_title shows a generic label. The hash is always present so anyone can still verify.

Reveal a sealed stamp

POST /stamps/:proof_id/reveal

Reveal a sealed stamp on-chain after its sealed_until date has passed. This uploads the content to Arweave and records the reveal on MegaETH. After reveal, GET /stamps/:proof_id returns the unsealed content.

Only the original stamp creator can reveal. Cost mirrors the underlying type: text = 1, URL = 2, file = 3 credits. Credits are refunded on any failure.

Example

Request

curl -X POST ".../api-v1/stamps/27/reveal" \
  -H "Authorization: Bearer ts_live_YOUR_KEY" \
  -H "apikey: YOUR_ANON_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: my-reveal-001"

Response 200

{
  "success": true,
  "proof_id": 27,
  "revealed": true,
  "tx_hash": "0xa490f00c...d3e3d",
  "arweave_uri": "ar://H3els0gCLLEW...jXc",
  "proof_url": "https://truthstamp.io/proof.html?id=27",
  "credits_charged": 1,
  "api_credits_remaining": 192
}

Error conditions

HTTPerrorMeaning
403not_ownerOnly the stamp creator can reveal it
400not_sealedThe stamp isn't a sealed stamp
400still_sealedReveal date hasn't passed yet
409already_revealedThis stamp was already revealed
402insufficient_api_creditsNot enough API credits
422reveal_failedOn-chain or Arweave failure; credits refunded

Reveal is synchronous and typically takes 15–30 seconds (Arweave upload + on-chain transaction). For revealing many stamps at once, loop client-side respecting your rate limit.

Verify content

POST /verify

Check whether a piece of content has been stamped. Provide either the raw content (which is hashed with SHA-256) or a content_hash directly. Returns the earliest stamp of that hash — proving when it first existed.

This works even for hash-only stamps: anyone holding the original content can prove it was stamped, although the content itself was never stored.

Request

curl -X POST ".../api-v1/verify" \
  -H "Authorization: Bearer ts_live_YOUR_KEY" \
  -H "apikey: YOUR_ANON_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "content": "secret content only I know" }'

Response 200 (found)

{
  "success": true,
  "verified": true,
  "content_hash": "0x64836320...058229b4",
  "first_stamped_at": "2026-06-17T14:39:34+00:00",
  "proof_id": 22,
  "visibility": "hash_only",
  "total_stamps_of_this_hash": 1,
  "proof_url": "https://truthstamp.io/proof.html?id=22"
}

Response 200 (not found)

{
  "success": true,
  "verified": false,
  "content_hash": "0xb94d27b9...2efcde9",
  "message": "No stamp found for this content hash..."
}

You can verify without creating anything — /verify does not consume credits.

Idempotency

To safely retry stamp creation without risking duplicates, send an Idempotency-Key header with a unique value (e.g. a UUID) per logical request. If a request with the same key has already succeeded, the original response is returned and no new stamp is created or charged.

-H "Idempotency-Key: 7c9e6679-7425-40de-944b-e07fc1f90ae7"

Keys are remembered for 24 hours. Only successful responses are stored, so a failed request can always be retried.

Rate limits

Each API key has a per-minute request limit (default 30/min). Exceeding it returns 429 rate_limited. If you need a higher limit, get in touch.

Error codes

Errors return a JSON body with success: false, a machine-readable error code, and a human-readable message.

HTTPerrorMeaning
401missing_api_keyNo Bearer key provided
401invalid_api_keyKey is wrong or revoked
402insufficient_api_creditsNot enough API credits
400missing_contentcontent field is empty
400invalid_urlURL must start with http:// or https://
400invalid_visibilityvisibility not recognised
400unsupported_content_typeOnly text and url in v1
400missing_sealed_untilSealed stamp without a reveal date
400seal_too_soonReveal date under 10 minutes away
409duplicate_contentThis exact content was already stamped
429rate_limitedPer-minute request limit exceeded
422stamp_failedStamping failed; credits refunded
403not_ownerReveal: only the stamp creator can reveal
400not_sealedReveal: stamp isn't sealed
400still_sealedReveal: reveal date hasn't passed yet
409already_revealedReveal: stamp was already revealed
422reveal_failedReveal: failed; credits refunded

On any failure during stamp creation, your API credits are automatically refunded — you are never charged for a stamp that did not succeed.