Claims API
The Claims API provides endpoints for creating, retrieving, updating, and deleting claims and subclaims, as well as creating and managing claim relations. Claims are atomic factual assertions extracted from or manually added to video summaries.
Overview
Claims support:
- Hierarchical structure (claims with subclaims)
- Typed relations between claims
- Automatic and manual creation
- Rich text with gloss references
- Confidence scores and attribution
- Async extraction via job queues
Data Model
Claim Object
{
id: string // UUID
summaryId: string // Parent summary UUID
summaryType: "video" | "collection"
text: string // Plain text content
gloss: GlossItem[] // Rich text with references
parentClaimId?: string | null // Parent claim (if subclaim)
textSpans?: ClaimTextSpan[] // Source spans in summary text
claimerType?: string | null // Who made the claim
claimerGloss?: GlossItem[] // Rich text for claimer
claimRelation?: GlossItem[] // Claim relation (believes, states, etc.)
claimEventId?: string | null // Event context
claimTimeId?: string | null // Temporal context
claimLocationId?: string | null // Spatial context
confidence?: number | null // 0-1 confidence score
modelUsed?: string | null // AI model ID (if extracted)
extractionStrategy?: string | null // sentence-based, semantic-units, hierarchical
createdBy?: string | null // User ID
createdAt: string // ISO 8601 timestamp
updatedAt: string // ISO 8601 timestamp
subclaims?: Claim[] // Nested subclaims (recursive)
}
GlossItem
{
type: "text" | "typeRef" | "objectRef" | "annotationRef" | "claimRef"
content: string
refType?: string // For typeRef
refPersonaId?: string | null // For typeRef
refClaimId?: string // For claimRef
}
ClaimTextSpan
{
sentenceIndex?: number // Sentence index in source
charStart: number // Character start position
charEnd: number // Character end position
}
ClaimRelation
{
id: string // UUID
sourceClaimId: string // Source claim UUID
targetClaimId: string // Target claim UUID
relationTypeId: string // Relation type from ontology
confidence?: number | null // 0-1 confidence score
notes?: string | null // Optional notes
createdAt: string // ISO 8601 timestamp
updatedAt: string // ISO 8601 timestamp
}
Endpoints
List Claims for Summary
Get all root claims for a video summary.
GET /api/summaries/:summaryId/claims
Query Parameters:
includeSubclaims(boolean, optional): Include nested subclaims (default: true)
Response 200:
[
{
"id": "claim-uuid",
"summaryId": "summary-uuid",
"summaryType": "video",
"text": "The rocket launched on December 25, 2021",
"gloss": [
{"type": "text", "content": "The rocket launched on December 25, 2021"}
],
"confidence": 0.95,
"modelUsed": "qwen-2-5-7b",
"extractionStrategy": "sentence-based",
"createdAt": "2025-01-20T10:30:00Z",
"updatedAt": "2025-01-20T10:30:00Z",
"subclaims": [
{
"id": "subclaim-uuid",
"parentClaimId": "claim-uuid",
"text": "Rocket launched",
"confidence": 0.98,
"createdAt": "2025-01-20T10:30:00Z",
"updatedAt": "2025-01-20T10:30:00Z"
}
]
}
]
Get Single Claim
Retrieve a specific claim by ID.
GET /api/claims/:claimId
Response 200:
{
"id": "claim-uuid",
"summaryId": "summary-uuid",
"text": "The rocket launched on December 25, 2021",
"gloss": [...],
"confidence": 0.95,
"subclaims": [...]
}
Response 404:
{
"error": "Claim not found"
}
Create Claim
Create a new claim or subclaim.
POST /api/summaries/:summaryId/claims
Content-Type: application/json
Request Body:
{
"summaryType": "video",
"text": "The rocket launched on December 25, 2021",
"gloss": [
{"type": "text", "content": "The rocket launched on December 25, 2021"}
],
"parentClaimId": null, // Optional: UUID of parent (for subclaims)
"textSpans": [ // Optional
{"sentenceIndex": 0, "charStart": 0, "charEnd": 42}
],
"claimerType": "author", // Optional
"confidence": 0.9 // Optional, 0-1
}
Response 201:
{
"id": "claim-uuid",
"summaryId": "summary-uuid",
"text": "The rocket launched on December 25, 2021",
"gloss": [...],
"confidence": 0.9,
"createdAt": "2025-01-20T10:30:00Z",
"updatedAt": "2025-01-20T10:30:00Z"
}
Update Claim
Update an existing claim.
PUT /api/claims/:claimId
Content-Type: application/json
Request Body:
{
"text": "Updated claim text",
"gloss": [...], // Optional
"confidence": 0.85, // Optional
"claimerType": "entity", // Optional
"notes": "Updated based on new evidence"
}
Response 200:
{
"id": "claim-uuid",
"text": "Updated claim text",
"confidence": 0.85,
"updatedAt": "2025-01-20T11:00:00Z"
}
Delete Claim
Delete a claim and all its subclaims (cascade).
DELETE /api/claims/:claimId
Response 200:
{
"message": "Claim and 3 subclaims deleted successfully"
}
Response 404:
{
"error": "Claim not found"
}
Claim Extraction
Start Claim Extraction Job
Extract claims from a video summary using AI.
POST /api/summaries/:summaryId/claims/extract
Content-Type: application/json
Request Body:
{
"strategy": "sentence-based", // sentence-based, semantic-units, hierarchical
"maxClaims": 50, // Max claims to extract
"minConfidence": 0.5, // Minimum confidence threshold (0-1)
"includeAnnotations": true, // Include @object references
"includeOntology": true, // Include #type references
"ontologyDepth": "names-only" // names-only, names-and-glosses, full
}
Response 202:
{
"jobId": "job-uuid",
"status": "queued",
"message": "Claim extraction job started"
}
Check Extraction Job Status
Poll job status until completion.
GET /api/jobs/:jobId
Response 200 (queued/active):
{
"jobId": "job-uuid",
"state": "active",
"progress": 65,
"createdAt": "2025-01-20T10:30:00Z",
"startedAt": "2025-01-20T10:30:15Z"
}
Response 200 (completed):
{
"jobId": "job-uuid",
"state": "completed",
"progress": 100,
"result": {
"claimIds": ["claim-1", "claim-2", "claim-3"],
"count": 3,
"extractionTime": 45.2
},
"createdAt": "2025-01-20T10:30:00Z",
"completedAt": "2025-01-20T10:31:15Z"
}
Response 200 (failed):
{
"jobId": "job-uuid",
"state": "failed",
"error": "Model service timeout",
"failedReason": "Connection timeout after 60s",
"createdAt": "2025-01-20T10:30:00Z",
"failedAt": "2025-01-20T10:31:00Z"
}
Claim Relations
List Relations for Claim
Get all outgoing and incoming relations for a claim.
GET /api/claims/:claimId/relations
Response 200:
{
"outgoing": [
{
"id": "relation-uuid",
"sourceClaimId": "claim-uuid",
"targetClaimId": "target-claim-uuid",
"relationTypeId": "supports",
"confidence": 0.85,
"notes": "Supporting evidence",
"createdAt": "2025-01-20T10:30:00Z"
}
],
"incoming": [
{
"id": "relation-uuid-2",
"sourceClaimId": "source-claim-uuid",
"targetClaimId": "claim-uuid",
"relationTypeId": "conflicts-with",
"confidence": 0.7,
"createdAt": "2025-01-20T10:35:00Z"
}
]
}
Create Claim Relation
Create a typed relation between two claims.
POST /api/claims/:sourceClaimId/relations
Content-Type: application/json
Request Body:
{
"targetClaimId": "target-claim-uuid",
"relationTypeId": "supports", // From ontology
"confidence": 0.85, // Optional, 0-1
"notes": "This claim provides supporting evidence"
}
Response 201:
{
"id": "relation-uuid",
"sourceClaimId": "source-claim-uuid",
"targetClaimId": "target-claim-uuid",
"relationTypeId": "supports",
"confidence": 0.85,
"notes": "This claim provides supporting evidence",
"createdAt": "2025-01-20T10:30:00Z",
"updatedAt": "2025-01-20T10:30:00Z"
}
Delete Claim Relation
Remove a relation between two claims.
DELETE /api/claims/relations/:relationId
Response 200:
{
"message": "Claim relation deleted successfully"
}
Filtering and Search
Filter Claims by Confidence
GET /api/summaries/:summaryId/claims?minConfidence=0.7
Returns only claims with confidence ≥ 0.7.
Search Claim Text
GET /api/summaries/:summaryId/claims?search=rocket
Returns claims containing "rocket" in text or gloss.
Filter by Extraction Strategy
GET /api/summaries/:summaryId/claims?strategy=sentence-based
Returns only claims extracted with "sentence-based" strategy.
Filter by Model
GET /api/summaries/:summaryId/claims?model=qwen-2-5-7b
Returns claims extracted by specific AI model.
Batch Operations
Delete All Claims for Summary
DELETE /api/summaries/:summaryId/claims
Response 200:
{
"message": "Deleted 25 claims successfully"
}
Bulk Create Claims
POST /api/summaries/:summaryId/claims/bulk
Content-Type: application/json
Request Body:
{
"claims": [
{
"text": "Claim 1",
"confidence": 0.9
},
{
"text": "Claim 2",
"confidence": 0.85
}
]
}
Response 201:
{
"created": 2,
"claimIds": ["claim-1", "claim-2"]
}
Error Responses
400 Bad Request
Invalid request data.
{
"error": "Validation error",
"details": [
{
"field": "confidence",
"message": "must be between 0 and 1"
}
]
}
401 Unauthorized
Not authenticated.
{
"error": "Authentication required"
}
404 Not Found
Resource not found.
{
"error": "Claim not found"
}
409 Conflict
Conflicting operation.
{
"error": "Claim relation already exists between these claims"
}
500 Internal Server Error
Server error.
{
"error": "Internal server error",
"message": "Database connection failed"
}
Examples
Complete Workflow: Extract and Edit Claims
// 1. Start extraction
const extractResponse = await fetch(
`/api/summaries/${summaryId}/claims/extract`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
strategy: 'hierarchical',
maxClaims: 20,
minConfidence: 0.7,
includeAnnotations: true
})
}
)
const { jobId } = await extractResponse.json()
// 2. Poll job status
let jobComplete = false
while (!jobComplete) {
const statusResponse = await fetch(`/api/jobs/${jobId}`)
const status = await statusResponse.json()
if (status.state === 'completed') {
jobComplete = true
console.log(`Extracted ${status.result.count} claims`)
} else if (status.state === 'failed') {
throw new Error(status.error)
}
await new Promise(resolve => setTimeout(resolve, 1000))
}
// 3. Get extracted claims
const claimsResponse = await fetch(`/api/summaries/${summaryId}/claims`)
const claims = await claimsResponse.json()
// 4. Update a claim
const claimId = claims[0].id
await fetch(`/api/claims/${claimId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
text: 'Updated claim text',
confidence: 0.95
})
})
// 5. Create a relation
await fetch(`/api/claims/${claimId}/relations`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
targetClaimId: claims[1].id,
relationTypeId: 'supports',
confidence: 0.85
})
})
Rate Limiting
Claims API endpoints are rate-limited:
- Extraction jobs: 10 per minute per user
- CRUD operations: 100 per minute per user
- Relation operations: 50 per minute per user
Exceeded limits return HTTP 429:
{
"error": "Rate limit exceeded",
"retryAfter": 30
}