DocsThe data protocol

claim/v3

packages/core/schema/claim-v3.schema.json
On this page

One attributed, immutable statement about an account, a contract or a group. Named by the SHA-256 of its RFC 8785 canonical JSON, without id and proof. The rules a schema can't say are in validateClaim, and petal.mjs validate-data runs them: an inferred claim states its grounds, in qualifiers.grounds, one or more of funding_lineage, inbound_transfers, research, same_address, shared_signer and synchronised_behaviour, sorted and joined by commas, and about a person, inbound_transfers alone isn't grounds enough; and a person's name in its words is allowed only in that person's own project. See specs/002-system/contracts/claims.md. v2 added annotations: a name, a note and a link in words (named, noted, linked), a person's own word (stated), research as a ground, and a transaction, a proposal and a quote in the evidence. v3 types each piece of evidence and says who found it and when, and an open source's platform and an archived copy, so a claim discovered on the chain, inferred, or gathered from the open web keeps what it rests on. A name or a person in its words is kept in a person's own project only (people.ts).

Fields

Field Type or allowed values Presence in its parent Description
petal "claim/v3" Required
id string Required
subject string Required Namespaced. refs.ts says which namespaces parse. No natural person.
verb "holds" / "measured" / "delegates_to" / "owned_by" / "member_of" / "holds_role" / "voted" / "proposed" / "reviewed" / "paid" / "funded_by" / "signer_of" / "deployed" / "controls" / "declares_same_controller" / "shares_signer" / "moves_with" / "same_funder" / "same_address" / "labelled" / "requests_correction" / "challenges" / "responds" / "retracts" / "supersedes" / "confidence" / "named" / "noted" / "linked" Required A closed list per version. Each verb's definition is in verbs.ts and contracts/claims.md.
object choice Required
object (variant 1) string Required Namespaced. refs.ts says which namespaces parse. No natural person.
object (variant 2) object Required
object (variant 2).value string Required A number as a string, a closed tag, or, for named, noted and linked, words or a link.
object (variant 2).unit string Optional
qualifiers object Optional Checked per verb. Amounts are strings.
qualifiers.* string Optional
valid_from string Optional UTC with Z, so one moment has one spelling and one id.
valid_to string Optional UTC with Z, so one moment has one spelling and one id.
issued_at string Required UTC with Z, so one moment has one spelling and one id.
as_of object Optional
as_of.chain string Required
as_of.block integer Required
kind "observed" / "declared" / "stated" / "sourced" / "inferred" Required
method string Optional Required if inferred: a rule or model, its version, and an optional hash of its parameters.
evidence array Required
evidence[] object Required
evidence[].snapshot_sha256 string Optional
evidence[].url string Optional
evidence[].url_sha256 string Optional
evidence[].retrieved_at string Optional UTC with Z, so one moment has one spelling and one id.
evidence[].claim_id string Optional
evidence[].note string Optional Short. In a published claim it must not name a person (people.ts).
evidence[].tx string Optional The transaction it rests on, on its chain: <caip2>:<hash>.
evidence[].proposal string Optional The proposal it rests on: proposal:<caip2>:<key>.
evidence[].quote string Optional The source's own words, exactly as written.
evidence[].type "snapshot" / "tx" / "proposal" / "page" / "post" / "claim" / "note" Required What this piece is: a reading by its hash, a transaction, a proposal, a web page, a post on a platform, another claim, or a note alone. It names the field that holds it.
evidence[].found_by string Required Who found this piece: an account, a named tool or a named model.
evidence[].found_at string Required When it was found.
evidence[].platform string Optional Where a page or post lives, as a slug: x, github, discord, forum, telegram, farcaster.
evidence[].archive_url string Optional An archived copy of the page or post (web.archive.org, archive.today), so it survives the page changing.
by string Required Namespaced. refs.ts says which namespaces parse. No natural person.
via string Optional Namespaced. refs.ts says which namespaces parse. No natural person.
proof choice Optional Outside the hash: the same claim can carry different proofs.
proof (variant 1) object Optional
proof (variant 1).type "tx" Required
proof (variant 1).hash string Required
proof (variant 2) object Optional
proof (variant 2).type "nep413" Required
proof (variant 2).account_id string Required
proof (variant 2).public_key string Required
proof (variant 2).signature string Required
proof (variant 2).message string Required
proof (variant 2).nonce string Required
proof (variant 2).recipient string Required
proof (variant 3) object Optional
proof (variant 3).type "nearai" Required
proof (variant 3).model string Required
proof (variant 3).completion_id string Required
proof (variant 3).text string Required
proof (variant 3).signature string Required
proof (variant 3).signing_address string Required
proof (variant 3).signing_algo "ecdsa" / "ed25519" Required

Examples

claim.v3.json

Fixture source

{
  "petal": "claim/v3",
  "subject": "eip155:100:0x1111111111111111111111111111111111111111",
  "verb": "named",
  "object": {
    "value": "Ada"
  },
  "issued_at": "2026-11-11T12:00:00Z",
  "kind": "sourced",
  "evidence": [
    {
      "type": "post",
      "url": "https://x.example/ada/status/1",
      "platform": "x",
      "quote": "Sending the handbook budget from 0x1111…1111, my keeper wallet.",
      "retrieved_at": "2026-11-11T11:30:00Z",
      "url_sha256": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
      "archive_url": "https://web.archive.org/web/20261111113000/https://x.example/ada/status/1",
      "found_by": "tool:codex@2026-11-10",
      "found_at": "2026-11-11T11:30:00Z"
    },
    {
      "type": "tx",
      "tx": "eip155:100:0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
      "note": "The transfer the post names, from this address.",
      "found_by": "tool:petal/observed-claims@1",
      "found_at": "2026-11-11T11:45:00Z"
    }
  ],
  "by": "near:mainnet:reed.example.near",
  "via": "tool:codex@2026-11-10",
  "id": "c157d4a25d48c15260d33d89a2aac9baddf3c72ae2981fea7e6886a8ff362c45"
}

Full schema

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "urn:petal:schema:claim:v3",
  "title": "Petal claim v3",
  "description": "One attributed, immutable statement about an account, a contract or a group. Named by the SHA-256 of its RFC 8785 canonical JSON, without id and proof. The rules a schema can't say are in validateClaim, and petal.mjs validate-data runs them: an inferred claim states its grounds, in qualifiers.grounds, one or more of funding_lineage, inbound_transfers, research, same_address, shared_signer and synchronised_behaviour, sorted and joined by commas, and about a person, inbound_transfers alone isn't grounds enough; and a person's name in its words is allowed only in that person's own project. See specs/002-system/contracts/claims.md. v2 added annotations: a name, a note and a link in words (named, noted, linked), a person's own word (stated), research as a ground, and a transaction, a proposal and a quote in the evidence. v3 types each piece of evidence and says who found it and when, and an open source's platform and an archived copy, so a claim discovered on the chain, inferred, or gathered from the open web keeps what it rests on. A name or a person in its words is kept in a person's own project only (people.ts).",
  "type": "object",
  "required": [
    "petal",
    "id",
    "subject",
    "verb",
    "object",
    "issued_at",
    "kind",
    "evidence",
    "by"
  ],
  "additionalProperties": false,
  "properties": {
    "petal": {
      "const": "claim/v3"
    },
    "id": {
      "$ref": "#/$defs/sha256"
    },
    "subject": {
      "$ref": "#/$defs/entityRef"
    },
    "verb": {
      "enum": [
        "holds",
        "measured",
        "delegates_to",
        "owned_by",
        "member_of",
        "holds_role",
        "voted",
        "proposed",
        "reviewed",
        "paid",
        "funded_by",
        "signer_of",
        "deployed",
        "controls",
        "declares_same_controller",
        "shares_signer",
        "moves_with",
        "same_funder",
        "same_address",
        "labelled",
        "requests_correction",
        "challenges",
        "responds",
        "retracts",
        "supersedes",
        "confidence",
        "named",
        "noted",
        "linked"
      ],
      "description": "A closed list per version. Each verb's definition is in verbs.ts and contracts/claims.md."
    },
    "object": {
      "oneOf": [
        {
          "$ref": "#/$defs/entityRef"
        },
        {
          "type": "object",
          "required": [
            "value"
          ],
          "additionalProperties": false,
          "properties": {
            "value": {
              "type": "string",
              "minLength": 1,
              "maxLength": 4000,
              "description": "A number as a string, a closed tag, or, for named, noted and linked, words or a link."
            },
            "unit": {
              "type": "string",
              "minLength": 1,
              "maxLength": 32
            }
          }
        }
      ]
    },
    "qualifiers": {
      "type": "object",
      "additionalProperties": {
        "type": "string",
        "maxLength": 256
      },
      "description": "Checked per verb. Amounts are strings."
    },
    "valid_from": {
      "$ref": "#/$defs/datetime"
    },
    "valid_to": {
      "$ref": "#/$defs/datetime"
    },
    "issued_at": {
      "$ref": "#/$defs/datetime"
    },
    "as_of": {
      "type": "object",
      "required": [
        "chain",
        "block"
      ],
      "additionalProperties": false,
      "properties": {
        "chain": {
          "type": "string",
          "pattern": "^[-a-z0-9]{3,8}:[-_a-zA-Z0-9]{1,32}$"
        },
        "block": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        }
      }
    },
    "kind": {
      "enum": [
        "observed",
        "declared",
        "stated",
        "sourced",
        "inferred"
      ]
    },
    "method": {
      "type": "string",
      "pattern": "^[a-zA-Z0-9][a-zA-Z0-9._/-]*@[a-zA-Z0-9][a-zA-Z0-9._/-]*(#[0-9a-f]{8,64})?$",
      "description": "Required if inferred: a rule or model, its version, and an optional hash of its parameters."
    },
    "evidence": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/evidence"
      }
    },
    "by": {
      "$ref": "#/$defs/entityRef"
    },
    "via": {
      "$ref": "#/$defs/entityRef"
    },
    "proof": {
      "oneOf": [
        {
          "$ref": "#/$defs/txProof"
        },
        {
          "$ref": "#/$defs/nep413Proof"
        },
        {
          "$ref": "#/$defs/nearAiProof"
        }
      ],
      "description": "Outside the hash: the same claim can carry different proofs."
    }
  },
  "if": {
    "type": "object",
    "properties": {
      "kind": {
        "const": "inferred"
      }
    },
    "required": [
      "kind"
    ]
  },
  "then": {
    "type": "object",
    "properties": {
      "method": true
    },
    "required": [
      "method"
    ]
  },
  "else": {
    "not": {
      "type": "object",
      "properties": {
        "method": true
      },
      "required": [
        "method"
      ]
    }
  },
  "$defs": {
    "sha256": {
      "type": "string",
      "pattern": "^[0-9a-f]{64}$"
    },
    "datetime": {
      "type": "string",
      "format": "date-time",
      "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]{1,9})?Z$",
      "description": "UTC with Z, so one moment has one spelling and one id."
    },
    "entityRef": {
      "type": "string",
      "pattern": "^[a-z][a-z0-9-]*:[^\\s]+$",
      "maxLength": 300,
      "description": "Namespaced. refs.ts says which namespaces parse. No natural person."
    },
    "evidence": {
      "type": "object",
      "minProperties": 1,
      "additionalProperties": false,
      "properties": {
        "snapshot_sha256": {
          "$ref": "#/$defs/sha256"
        },
        "url": {
          "type": "string",
          "minLength": 1,
          "maxLength": 2048
        },
        "url_sha256": {
          "$ref": "#/$defs/sha256"
        },
        "retrieved_at": {
          "$ref": "#/$defs/datetime"
        },
        "claim_id": {
          "$ref": "#/$defs/sha256"
        },
        "note": {
          "type": "string",
          "minLength": 1,
          "maxLength": 280,
          "description": "Short. In a published claim it must not name a person (people.ts)."
        },
        "tx": {
          "type": "string",
          "pattern": "^[-a-z0-9]{3,8}:[-_a-zA-Z0-9]{1,32}:[0-9a-zA-Z]{16,128}$",
          "description": "The transaction it rests on, on its chain: <caip2>:<hash>."
        },
        "proposal": {
          "$ref": "#/$defs/entityRef",
          "description": "The proposal it rests on: proposal:<caip2>:<key>."
        },
        "quote": {
          "type": "string",
          "minLength": 1,
          "maxLength": 1000,
          "description": "The source's own words, exactly as written."
        },
        "type": {
          "enum": [
            "snapshot",
            "tx",
            "proposal",
            "page",
            "post",
            "claim",
            "note"
          ],
          "description": "What this piece is: a reading by its hash, a transaction, a proposal, a web page, a post on a platform, another claim, or a note alone. It names the field that holds it."
        },
        "found_by": {
          "$ref": "#/$defs/entityRef",
          "description": "Who found this piece: an account, a named tool or a named model."
        },
        "found_at": {
          "$ref": "#/$defs/datetime",
          "description": "When it was found."
        },
        "platform": {
          "type": "string",
          "pattern": "^[a-z0-9][a-z0-9._-]{0,31}$",
          "description": "Where a page or post lives, as a slug: x, github, discord, forum, telegram, farcaster."
        },
        "archive_url": {
          "type": "string",
          "minLength": 1,
          "maxLength": 2048,
          "description": "An archived copy of the page or post (web.archive.org, archive.today), so it survives the page changing."
        }
      },
      "required": [
        "type",
        "found_by",
        "found_at"
      ]
    },
    "txProof": {
      "type": "object",
      "required": [
        "type",
        "hash"
      ],
      "additionalProperties": false,
      "properties": {
        "type": {
          "const": "tx"
        },
        "hash": {
          "type": "string",
          "minLength": 1
        }
      }
    },
    "nep413Proof": {
      "type": "object",
      "required": [
        "type",
        "account_id",
        "public_key",
        "signature",
        "message",
        "nonce",
        "recipient"
      ],
      "additionalProperties": false,
      "properties": {
        "type": {
          "const": "nep413"
        },
        "account_id": {
          "type": "string"
        },
        "public_key": {
          "type": "string",
          "pattern": "^ed25519:"
        },
        "signature": {
          "type": "string"
        },
        "message": {
          "type": "string"
        },
        "nonce": {
          "type": "string"
        },
        "recipient": {
          "type": "string"
        }
      }
    },
    "nearAiProof": {
      "type": "object",
      "required": [
        "type",
        "model",
        "completion_id",
        "text",
        "signature",
        "signing_address",
        "signing_algo"
      ],
      "additionalProperties": false,
      "properties": {
        "type": {
          "const": "nearai"
        },
        "model": {
          "type": "string"
        },
        "completion_id": {
          "type": "string"
        },
        "text": {
          "type": "string"
        },
        "signature": {
          "type": "string"
        },
        "signing_address": {
          "type": "string"
        },
        "signing_algo": {
          "enum": [
            "ecdsa",
            "ed25519"
          ]
        }
      }
    }
  }
}