Skip to content

Chronicles Overview

Chronicles are a flexible system for recording custom, time-based information within the Worlds API. They allow API consumers to define and organize activities, events, and summaries specific to their business use cases. Chronicles are created and managed through chronicle producers, which represent the custom processes responsible for detecting and recording chronicles.

A chronicle producer represents a custom process that detects and records chronicles. Before creating any chronicles, you must create a chronicle producer to own them. It is recommended to create a separate producer for each distinct use case, which keeps chronicle data well-organized and allows independent configuration per use case. A single producer can be reused across multiple sites if the use case is the same.

For example, a grocery store chain might create the following producers:

  • Customer Tracking — records customer visits across all store locations
  • Safety Monitoring — records hazard events such as spills and fallen objects

Each producer can be configured with a name, description, timezone, and arbitrary metadata.

mutation {
createChronicleProducer(chronicleProducer: {
name: "Safety Monitoring"
description: "Tracks hazard events such as spills and fallen objects"
active: true
timezone: "America/New_York"
}) {
id
name
}
}

There are three types of chronicles, each suited to different kinds of time-based information. All three share a common set of fields including name, description, metadata, priority, status, labels, locations, timezone, and validation. Each chronicle is owned by a chronicle producer and can be used independently or in combination with other chronicles.

An activity chronicle represents a behavior with a fixed timespan. Activities have a startTime and an optional endTime, making them well-suited for tracking ongoing or completed processes.

Activities are the richest chronicle type, supporting associations to tracks, sites, data sources, images, clips, tags, and points of interest. When creating an activity, you can provide IDs for these associated objects to link them directly. For example, a customer visit activity can include the track IDs for all tracks of that customer observed between the customer entering and leaving the store.

Example activities in a grocery store:

  • Customer Visit — tracks a single customer’s time in the store from entry to exit, with associated track IDs linking to the detection data for that visit.
  • Employee Shift — records the start and end of an employee’s working shift, with metadata capturing the employee’s role or assigned department.
mutation {
createActivityChronicle(activityChronicle: {
chronicleProducerId: "producer-id"
name: "Customer Visit"
description: "Customer entered via the north entrance and visited aisles 3, 7, and 12."
startTime: "2026-03-24T09:15:00-04:00"
endTime: "2026-03-24T09:42:00-04:00"
labels: ["customer-visit"]
locations: ["Store #401"]
trackIds: ["track-1", "track-2"]
metadata: { entrance: "north", aislesVisited: [3, 7, 12] }
}) {
id
name
startTime
endTime
}
}

An event chronicle represents an occurrence at a single point in time. Events have a timestamp rather than a time range, making them ideal for recording discrete moments.

Events can reference activity chronicles. This is useful when an event is meaningfully related to one or more activities. For instance, a hazard event might reference the employee shift activity of the worker who reported or responded to the hazard.

Example events in a grocery store:

  • Checkout — records the moment a customer completes a purchase at a register.
  • Hazard Detected — records the moment a spill or fallen object is identified, referencing the employee shift activity of the employee nearest to the incident.
mutation {
createEventChronicle(eventChronicle: {
chronicleProducerId: "producer-id" #this would typically be a UUID in practice
name: "Hazard Detected"
description: "Liquid spill detected in aisle 7 near the dairy section."
timestamp: "2026-03-24T14:30:00-04:00"
labels: ["hazard", "spill"]
locations: ["Store #401", "Aisle 7"]
priority: "high"
activityChronicleIds: ["employee-shift-id"] #this would typically be a UUID in practice
}) {
id
name
timestamp
}
}

A summary chronicle summarizes information across a specific timeframe. Summaries have both a required startTime and endTime, defining the range they cover. They can reference both activity chronicles and event chronicles to aggregate related data into a single record.

Summaries are flexible in how they reference other chronicles. A summary may link to specific chronicles when individual references are useful, or it may simply store aggregate data in its metadata field without referencing individual chronicles. The choice depends on the needs of the consuming application.

Example summaries in a grocery store:

  • Daily Store Report — summarizes a full day of operations, with metadata containing aggregate counts such as the total number of customer visits.
    • Individual customer visit activities are not referenced because the business use case only requires the totals.
  • Daily Hazard Report — summarizes all hazard events for a single day, referencing each hazard event chronicle directly so that consumers can navigate from the summary to the specific incidents.
mutation {
createSummaryChronicle(summaryChronicle: {
chronicleProducerId: "producer-id" #this would typically be a UUID in practice
name: "Daily Store Report"
description: "Summary of operations for Store #401 on March 24, 2026."
startTime: "2026-03-24T00:00:00-04:00"
endTime: "2026-03-25T00:00:00-04:00"
labels: ["daily-report"]
locations: ["Store #401"]
metadata: { customerVisits: 42, averageVisitMinutes: 28 }
}) {
id
name
}
}
mutation {
createSummaryChronicle(summaryChronicle: {
chronicleProducerId: "producer-id" #this would typically be a UUID in practice
name: "Daily Hazard Report"
description: "All hazard events for Store #401 on March 24, 2026."
startTime: "2026-03-24T00:00:00-04:00"
endTime: "2026-03-25T00:00:00-04:00"
labels: ["hazard-report"]
locations: ["Store #401"]
eventChronicleIds: ["hazard-event-1", "hazard-event-2"] #these would typically be UUIDs in practice
metadata: { totalHazards: 2, resolvedCount: 1 }
}) {
id
name
eventChronicles { id name timestamp }
}
}

Chronicles support an optional validation workflow for cases where human verification of chronicle accuracy is desired. Each chronicle can carry a validation field with a status of VALID or INVALID, along with an optional reason (required when marking as INVALID) and details.

This is useful in scenarios such as a safety supervisor reviewing hazard events to confirm they are genuine, or a manager verifying that a flagged customer visit was correctly categorized.

Existing events and event producers are automatically synced to activity chronicles and chronicle producers, respectively. New activity chronicles and chronicle producers are also back-synced to events and event producers, allowing consumers to incrementally migrate to chronicles at their own pace.

When migrating, consider the most appropriate chronicle type for each legacy event.
Legacy events require a startTime and endTime to be recorded, so activity chronicles will make sense in many cases. However, an event chronicle may be more appropriate when the event is treated as a single moment in time.

Event producers map directly to chronicle producers. All fields carry over with the same values, with one rename:

Event ProducerChronicle Producer
idid
namename
descriptiondescription
timezonetimezone
activeactive
metadatametadata
invalidReasonsvalidationReasons

Events are synced to activity chronicles. Most fields map directly, but there are a few notable differences:

EventActivity ChronicleNotes
typenameEvent type becomes the activity’s name.
subTypedescriptionEvent subType becomes description. Note that description is intended for plain-language descriptions going forward. labels are typically more appropriate for specific categories.
startTimestartTime
endTimeendTime
positionposition
timezonetimezone
metadatametadata
prioritypriority
imagesimages
dataSourceClipsdataSourceClips
validationvalidation
draftstatusEvents with draft: true are synced with a status of "draft".
properties.trackstracksMoved from nested properties to a top-level field.
properties.sitessitesMoved from nested properties to a top-level field.
properties.dataSourcesdataSourcesMoved from nested properties to a top-level field.
properties.tagstagsMoved from nested properties to a top-level field.
properties.pointsOfInterestpointsOfInterestMoved from nested properties to a top-level field.

Activity chronicle fields labels, locations, and status (when not derived from draft) are not populated from legacy event data.