{
"id": "at.margin.annotation",
"defs": {
"body": {
"type": "object",
"properties": {
"uri": {
"type": "string",
"format": "uri",
"description": "Reference to external body content"
},
"value": {
"type": "string",
"maxLength": 10000,
"description": "Text content of the annotation",
"maxGraphemes": 3000
},
"format": {
"type": "string",
"default": "text/plain",
"description": "MIME type of the body content"
},
"language": {
"type": "string",
"description": "BCP47 language tag"
}
},
"description": "Annotation body - the content of the annotation"
},
"main": {
"key": "tid",
"type": "record",
"record": {
"type": "object",
"required": [
"target",
"createdAt"
],
"properties": {
"body": {
"ref": "#body",
"type": "ref",
"description": "The annotation content (text or reference)"
},
"tags": {
"type": "array",
"items": {
"type": "string",
"maxLength": 64,
"maxGraphemes": 32
},
"maxLength": 10,
"description": "Tags for categorization"
},
"labels": {
"ref": "com.atproto.label.defs#selfLabels",
"type": "ref",
"description": "Self-applied content labels for this annotation"
},
"rights": {
"type": "string",
"format": "uri",
"description": "License URI (e.g., https://creativecommons.org/licenses/by/4.0/)"
},
"target": {
"ref": "#target",
"type": "ref",
"description": "The resource being annotated with optional selector"
},
"createdAt": {
"type": "string",
"format": "datetime"
},
"generator": {
"ref": "#generator",
"type": "ref",
"description": "The client/agent that created this record"
},
"motivation": {
"type": "string",
"description": "W3C motivation for the annotation",
"knownValues": [
"commenting",
"highlighting",
"bookmarking",
"tagging",
"describing",
"linking",
"replying",
"editing",
"questioning",
"assessing"
]
}
}
},
"description": "A W3C-compliant web annotation stored on the AT Protocol"
},
"target": {
"type": "object",
"required": [
"source"
],
"properties": {
"state": {
"ref": "#timeState",
"type": "ref",
"description": "State of the resource at annotation time"
},
"title": {
"type": "string",
"maxLength": 500,
"description": "Page title at time of annotation"
},
"source": {
"type": "string",
"format": "uri",
"description": "The URL being annotated"
},
"selector": {
"refs": [
"#textQuoteSelector",
"#textPositionSelector",
"#cssSelector",
"#xpathSelector",
"#fragmentSelector",
"#rangeSelector"
],
"type": "union",
"description": "Selector to identify the specific segment"
},
"sourceHash": {
"type": "string",
"description": "SHA256 hash of normalized URL for indexing"
}
},
"description": "W3C SpecificResource - the target with optional selector"
},
"generator": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uri"
},
"name": {
"type": "string"
},
"homepage": {
"type": "string",
"format": "uri"
}
},
"description": "The client/agent that created this record"
},
"timeState": {
"type": "object",
"properties": {
"cached": {
"type": "string",
"format": "uri",
"description": "URL to cached/archived version"
},
"sourceDate": {
"type": "string",
"format": "datetime",
"description": "When the source was accessed"
}
},
"description": "W3C TimeState - record when content was captured"
},
"cssSelector": {
"type": "object",
"required": [
"value"
],
"properties": {
"type": {
"type": "string",
"const": "CssSelector"
},
"value": {
"type": "string",
"maxLength": 2000,
"description": "CSS selector string"
}
},
"description": "W3C CssSelector - select DOM elements by CSS selector"
},
"rangeSelector": {
"type": "object",
"required": [
"startSelector",
"endSelector"
],
"properties": {
"type": {
"type": "string",
"const": "RangeSelector"
},
"endSelector": {
"refs": [
"#textQuoteSelector",
"#textPositionSelector",
"#cssSelector",
"#xpathSelector"
],
"type": "union",
"description": "Selector for range end"
},
"startSelector": {
"refs": [
"#textQuoteSelector",
"#textPositionSelector",
"#cssSelector",
"#xpathSelector"
],
"type": "union",
"description": "Selector for range start"
}
},
"description": "W3C RangeSelector - select range between two selectors"
},
"xpathSelector": {
"type": "object",
"required": [
"value"
],
"properties": {
"type": {
"type": "string",
"const": "XPathSelector"
},
"value": {
"type": "string",
"maxLength": 2000,
"description": "XPath expression"
}
},
"description": "W3C XPathSelector - select by XPath expression"
},
"fragmentSelector": {
"type": "object",
"required": [
"value"
],
"properties": {
"type": {
"type": "string",
"const": "FragmentSelector"
},
"value": {
"type": "string",
"maxLength": 1000,
"description": "Fragment identifier value"
},
"conformsTo": {
"type": "string",
"format": "uri",
"description": "Specification the fragment conforms to"
}
},
"description": "W3C FragmentSelector - select by URI fragment"
},
"textQuoteSelector": {
"type": "object",
"required": [
"exact"
],
"properties": {
"type": {
"type": "string",
"const": "TextQuoteSelector"
},
"exact": {
"type": "string",
"maxLength": 5000,
"description": "The exact text to match",
"maxGraphemes": 1500
},
"prefix": {
"type": "string",
"maxLength": 500,
"description": "Text immediately before the selection",
"maxGraphemes": 150
},
"suffix": {
"type": "string",
"maxLength": 500,
"description": "Text immediately after the selection",
"maxGraphemes": 150
}
},
"description": "W3C TextQuoteSelector - select text by quoting it with context"
},
"textPositionSelector": {
"type": "object",
"required": [
"start",
"end"
],
"properties": {
"end": {
"type": "integer",
"minimum": 0,
"description": "Ending character position (exclusive)"
},
"type": {
"type": "string",
"const": "TextPositionSelector"
},
"start": {
"type": "integer",
"minimum": 0,
"description": "Starting character position (0-indexed, inclusive)"
}
},
"description": "W3C TextPositionSelector - select by character offsets"
}
},
"$type": "com.atproto.lexicon.schema",
"lexicon": 1,
"revision": 2,
"description": "W3C Web Annotation Data Model compliant annotation record for ATProto"
}