Base URL: https://node.theailab.org
Version: v1
Format: All requests and responses use application/json
Auth: Admin endpoints require Authorization: Bearer <TIP_ADMIN_API_KEY>
Returns node health status.
Response 200:
{
"status": "ok",
"version": "2.0.0",
"chain_id": "tip-mainnet-v2",
"dag_count": 1842,
"uptime_seconds": 86400
}Returns full node metadata.
Response 200:
{
"node_id": "tip://id/US-nodehash12345678",
"protocol_version": "2.0",
"chain_id": "tip-mainnet-v2",
"genesis_hash": "52f08c352f8866b4...",
"vp_mode": false,
"peer_count": 12
}Returns known peer nodes.
Response 200:
{ "peers": ["node1.example.com:4001", "node2.example.com:4001"] }Returns DAG statistics.
Response 200:
{
"tx_count": 1842,
"identity_count": 423,
"content_count": 891,
"vp_count": 7
}Register a new TIP-ID. Requires VP signature.
Request body:
{
"tip_id": "tip://id/US-a3f8c91b2d4e7021",
"region": "US",
"public_key": "[ML-DSA-65 public key hex]",
"vp_id": "tip://id/VP-US-example",
"dedup_hash": "[peppered SHAKE-256 dedup hash]",
"zk_proof": "[ZK proof of uniqueness]",
"vp_signature": "[ML-DSA-65 signature by VP over tip_id+dedup_hash]",
"attested": false
}Response 201:
{
"tip_id": "tip://id/US-a3f8c91b2d4e7021",
"status": "active",
"score": 500,
"tier": { "label": "REVIEW_ADVISED", "color": "#A88B15" },
"verified_at": "2026-03-15T00:00:00Z"
}Errors:
400: Missing required fields409: TIP-ID already registered422: Duplicate identity (dedup_hash exists)403: Invalid VP signature or VP not accredited
Resolve a TIP-ID. URL-encode the TIP-ID.
Response 200:
{
"tip_id": "tip://id/US-a3f8c91b2d4e7021",
"region": "US",
"status": "active",
"vp_id": "tip://id/VP-US-example",
"verified_at": "2026-03-15T00:00:00Z",
"score": 892,
"tier": { "label": "HIGHLY_TRUSTED", "color": "#1A8A5C" },
"founding": false
}Errors: 404: TIP-ID not found
Get trust score only (lightweight endpoint for embedding).
Response 200:
{
"tip_id": "tip://id/US-a3f8c91b2d4e7021",
"score": 892,
"tier": { "label": "HIGHLY_TRUSTED", "color": "#1A8A5C" },
"offense_count": 0,
"status": "active",
"display_mode": "TIER_ONLY"
}Get transaction history for a TIP-ID.
Response 200:
{
"tip_id": "tip://id/US-a3f8c91b2d4e7021",
"events": [
{ "tx_type": "REGISTER_IDENTITY", "timestamp": "2026-03-15T00:00:00Z", "delta": 0 },
{ "tx_type": "CONTENT_VERIFIED", "timestamp": "2026-03-16T00:00:00Z", "delta": 3 }
]
}Register content with origin declaration.
Request body:
{
"author_tip_id": "tip://id/US-a3f8c91b2d4e7021",
"origin_code": "OH",
"content": "Article text or base64-encoded media...",
"title": "Article Title",
"author_signature": "[ML-DSA-65 signature over content+origin_code]"
}Response 201:
{
"ctid": "tip://c/OH-7f2a91bc3d5e4a-a3f8",
"status": "verified",
"origin_code": "OH",
"content_hash": "[SHAKE-256 hex]",
"registered_at": "2026-03-15T00:00:00Z",
"pre_scan": { "flagged": false, "probability": 0.12 }
}If pre-scan flags the content, status will be pending and pre_scan.flagged will be true. The content is still registered.
Errors:
400: Missing required fields or invalid origin code403: Author TIP-ID not active422: Invalid author signature
Resolve a content provenance record.
Response 200:
{
"ctid": "tip://c/OH-7f2a91bc3d5e4a-a3f8",
"origin_code": "OH",
"origin_label": "Original Human",
"status": "verified",
"author_tip_id": "tip://id/US-a3f8c91b2d4e7021",
"author_score": 892,
"dispute_count": 0,
"registered_at": "2026-03-15T00:00:00Z",
"media": [
{
"media_id": "[SHAKE-256 hex of the bytes]",
"mime": "image/png",
"stored": true,
"size": 2361613,
"ai_probability": 0.51,
"ai_provider": "image_detector"
}
],
"media_canonical_hash": "[SHAKE-256 hex]"
}media[] carries public storage facts (type, size, whether the bytes are still stored) and the per-file AI score from the verdict. The bytes themselves are not here, fetch them via the role-gated media endpoint below. ai_probability is null until prescan completes.
List content, newest first. Cursor-paginated, public.
Query params (all optional): author, origin, status, has_media, limit (1-100, default 20), cursor (opaque token from a prior response's next_cursor).
Response 200: { "items": [ ...slim rows... ], "next_cursor": "..." | null }. Each row carries ctid, author_tip_id, origin_code, status, prescan_status, prescan_tier, media_count, registered_urls, registered_at.
File a dispute against a content origin declaration.
Request body:
{
"disputer_tip_id": "tip://id/VP-US-example",
"reason": "AI classifier detected probable AI generation in OH-declared content",
"evidence_hash": "[SHAKE-256 of classifier output]"
}Response 201:
{
"success": true,
"message": "Dispute filed. Stage 1 AI classifier will run within 60 seconds.",
"dispute_id": "tx_id_of_dispute_transaction"
}Manually verify a content record (jury-level participants only).
Media bytes are content-addressed (media_id = SHAKE-256(bytes)), stored off-chain per node, and access-controlled by adjudication role. Only the content-hash references live on chain. See docs/user-journeys for the role-access model.
Upload one file. Body is the raw bytes (Content-Type: application/octet-stream), one file per call, streamed.
Headers: X-Media-Mime, X-Signer-TipId, X-Timestamp (epoch ms, 5-min window), X-Signer-Signature (ML-DSA over MEDIA_UPLOAD:{shake256(bytes)}:{mime}:{timestamp}:{signer_tip_id}).
Response 201: { media_id, content_hash, mime, size, uploaded_at, signer_tip_id }. The mime is SERVER-DETECTED from the file's magic bytes and is authoritative, use it (not your own label) when registering. Identical bytes always return the same media_id (dedup).
Errors: 400 timestamp_drift / bytes_required; 403 signature_invalid; 413 file_too_large (aborts mid-stream, sends Connection: close); 415 mime_disabled / format_unsupported.
Fetch media bytes. Role-gated, signed. The public cannot fetch bytes (only the metadata on the content record).
Headers: X-Requester-TipId, X-Timestamp, X-Signature (ML-DSA over MEDIA_ACCESS:{ctid}:{idx}:{timestamp}:{requester_tip_id}).
Allowed callers: author (always), assigned reviewer (until the review closes), disputer (while the dispute lives), juror (until ADJUDICATION_RESULT), expert (until APPEAL_RESULT). Everyone else gets 403 forbidden.
Responses: 200 raw bytes (local-fs node) or 200 JSON { presigned_url, expires_at } (S3 node, fetch the URL within ~5 min); 307 redirect to the origin node (bytes live elsewhere, repeat the same signed request to Location); 410 media_unavailable (retention-deleted, the hash on chain remains the proof).
Public key-rotation chain for an identity, oldest first: { tip_id, rotations, keys: [{ public_key, algorithm, valid_from_ts, valid_to_ts, source_tx_id }] }. Used for client-side verification: tip_id anchors shake256(keys[0].public_key), and each later key is introduced by the signed rotation tx in source_tx_id.
Get all current revocations.
Response 200:
{
"revocations": [
{
"tip_id": "tip://id/US-revokeduser1",
"tx_type": "REVOKE_VOLUNTARY",
"timestamp": "2026-03-15T00:00:00Z"
}
]
}Create a revocation. Requires admin auth.
Request body:
{
"tip_id": "tip://id/US-a3f8c91b2d4e7021",
"tx_type": "REVOKE_VOLUNTARY",
"reason": "User requested permanent revocation",
"requester_id": "tip://id/US-a3f8c91b2d4e7021",
"signature": "[ML-DSA-65 signature over tip_id+tx_type]"
}For REVOKE_VP, additionally include:
{
"evidence_hash": "[SHAKE-256 of evidence document]",
"issuing_vp_id": "tip://id/VP-US-example"
}Check if an identity is unique. Returns boolean only: never reveals the hash.
Request body:
{
"dedup_hash": "[peppered SHAKE-256 hash]",
"zk_proof": "[ZK proof of uniqueness]"
}Response 200:
{ "is_unique": true }Get the current Merkle root of the dedup registry (published every 6 hours).
Response 200:
{
"merkle_root": "[SHAKE-256 Merkle root hex]",
"count": 423,
"published_at": "2026-03-15T06:00:00Z"
}Register a new VP. Requires admin auth.
Request body:
{
"vp_id": "tip://id/VP-US-example",
"public_key": "[ML-DSA-65 public key hex]",
"jurisdiction_tier": "GREEN",
"country": "US",
"operator_name": "Example Identity Services LLC"
}Get VP details.
Response 200:
{
"vp_id": "tip://id/VP-US-example",
"status": "active",
"jurisdiction_tier": "GREEN",
"country": "US",
"operator_name": "Example Identity Services LLC",
"registered_at": "2026-03-15T00:00:00Z"
}| Endpoint Group | Limit (unauthenticated) | Limit (admin auth) |
|---|---|---|
| Read endpoints | 100 req/min per IP | 1000 req/min |
| Write endpoints | 20 req/min per IP | 200 req/min |
| Admin endpoints | N/A | 50 req/min |
All errors return JSON:
{
"error": "description of the error",
"code": "machine-readable error code",
"details": { "field": "additional context" }
}Copyright 2026 The AI Lab Intelligence Unobscured, Inc. | TIPCL-1.0