Skip to main content
The Events Timeline is the unified event stream that connects every Axiom product. It contains ~1.7M events from 16+ source normalizers covering permits, council votes, AIS dark events, port calls, regulatory filings, POI lifecycle changes, crop health alerts, and more. Every other Codex dataset references an event_id from this timeline, making it the graph spine across the catalog. Records are ingested continuously and published as monthly immutable snapshots. Every record inherits the full APRS envelope and carries the join keys documented below.

Dataset-specific fields

FieldTypeNullableDescription
event_typedotted stringnoHierarchical event type. See event taxonomy.
event_categoryenumnoHigh-level grouping: maritime, civic, regulatory, poi, environmental, economic, risk.
entity_idstringnoCanonical key for the affected entity. Shape depends on entity_type.
entity_typeenumnoType of the affected entity. See entity types.
entity_namestringyesHuman-readable name (display only).
locationPostGIS PointyesWGS84 geometry. Use h3_index for joins.
location_namestringyesHuman-readable location description.
h3_indexstringyesH3 resolution-8 cell derived from location.
started_attimestamptznoWhen the real-world event began.
resolved_attimestamptzyesWhen the event closed. Null if still open or point-in-time.
magnitudefloatyesEvent-specific magnitude. Unit varies by event_type. See magnitude units.
confidencefloat [0,1]yesPipeline confidence that the event is real.
sourcestringnoOriginating pipeline (aisstream, socrata, granicus, etc.).
source_refstringyesSource-native reference for re-fetch.
productenumnoGenerating product: locus, overwatch, or codex.
downstream_outcomestringyesPost-hoc outcome annotation from cascade detectors.
outcome_lag_daysintegeryesDays between this event and its downstream outcome.
metadataJSONByesEvent-specific overflow fields. See metadata keys.
jurisdiction_slugstringyesPopulated for civic and regulatory events.

Event taxonomy

Event types use a {domain}.{verb} convention. You can filter at the family level (event_type LIKE 'port.%') or by specific action.

Maritime events

TypeDescription
port.enteredVessel crossed port polygon inbound
port.anchoredVessel reported anchored status inside port
port.berthedVessel matched to a specific berth
port.departedVessel crossed port polygon outbound
visit.in_progressOpen vessel visit, no departure yet
visit.completedPaired entry and departure. magnitude = visit duration in hours
dark_eventAIS gap plus kinematic violation
satellite.{alert_type}Per-alert-type subtype (e.g., vessel_cluster, dark_emission)

Civic events

TypeDescription
council.approvedCouncil vote in favor
council.deniedCouncil vote against
council.tabledMotion tabled or deferred
council.mentionedTopic mentioned, no decision
permit.filedNew permit application
permit.approvedPermit approved
permit.deniedPermit denied
permit.expiredPermit aged out without completion
permit.completedWork finaled
permit.cancelledWithdrawn by applicant
permit.revokedRevoked by authority
noise_complaint311 noise complaint
business_licenseNew license issued

Regulatory events

TypeDescription
regulatory.filingSEC 8-K, 10-K, etc.
regulatory.enforcementFDA, EPA, or OSHA action
regulatory.complaintConsumer or worker complaint filing
regulatory.noticeAuthority notice
regulatory.ruleFinal rule publication

POI events

TypeDescription
poi.openedFirst observation of a new POI
poi.activeOngoing POI observation
poi.temporarily_closedTemporary closure
poi.closedPermanently closed

Environmental events

TypeDescription
environmental.disasterFEMA/NWS disaster declaration
crop.ndvi_dropSentinel-2 NDVI decline. magnitude = percent change
crop.ndvi_recoveryNDVI recovery
river.{status}Gauge status subtype (flood, action, normal)

Economic events

TypeDescription
jobs.snapshotPeriodic snapshot of active postings per cell. magnitude = listing count
migration.inflowNet positive migration. magnitude = net persons
migration.outflowNet negative migration
trade.{flow_type}Customs/CBP trade flow subtype

Risk events

TypeDescription
risk.criticalRisk score >= 85
risk.elevatedRisk score >= 60
risk.moderateRisk score >= 30
risk.lowRisk score < 30

Entity types

The shape of entity_id depends on entity_type:
Entity typeentity_id shapeExample
vesselIMO number (preferred) or MMSI9432871
parcel{jurisdiction_slug}:{parcel-number}philadelphia-pa:12-345-678
permitpermit:{jurisdiction}:{permit-id}permit:sf-ca:2024-0412
council_matterlegistar:{jurisdiction}:{matter-id}legistar:phila-pa:24-0031
poiurn:aprs:record:poi:{source}:{id}urn:aprs:record:poi:fsq:abc123
organizationurn:aprs:entity:company:{id}urn:aprs:entity:company:acme-llc
personurn:aprs:entity:person:{id}urn:aprs:entity:person:j-doe
h3_cellH3 resolution-8 string88283082b9fffff
jurisdictionjurisdiction_slugphiladelphia-pa

Magnitude units

magnitude is polymorphic — its unit depends on event_type. Always check event_type before comparing magnitude values.
Event type patternUnit
visit.completedHours (visit duration)
dark_eventHours (AIS gap)
crop.ndvi_*Percent change vs. 5-year baseline
jobs.snapshotCount of active postings
migration.*Net persons
trade.*USD value (notional)
risk.*Risk score 0–100
permit.* (with metadata.declared_value)USD value

Metadata keys

The metadata JSONB column holds type-specific fields. Keys are version-bound — a key present in one event type is not guaranteed in another.
KeyEvent typesDescription
kinematic_metadark_eventImplied speed, Froude limit, OU max reach, actual distance, failed tests
psc_detention_historyMaritime eventsPort State Control detentions linked to this event
declared_valuepermit.*USD value declared on the permit
voting_tallycouncil.*{yes, no, abstain, absent}
alert_type_rawsatellite.*Upstream alert code
related_event_idsAnyArray of event_id UUIDs this event is linked to. See event chains
mmsiMaritimeMMSI when entity_type='vessel'
imoMaritimeIMO number when known
parcel_idCivic (permits/zoning)Parcel identifier

Event chains

Events are often cascading effects of earlier events. The metadata.related_event_ids field links events into chains:
  • Maritime dark event chain: port.departeddark_eventport.entered (different port)
  • Permit cascade: council.approvedpermit.filedpermit.approvedpermit.completed
  • Risk cascade: regulatory.enforcementrisk.critical

Traversal example

Find every downstream civic event following a dark event within 12 months:
WITH RECURSIVE chain AS (
  SELECT id, event_type, started_at, metadata
  FROM codex.events_timeline
  WHERE id = 'c5a8e4f2-9b7d-4c1e-b3a5-1f2d8c0e7a93'

  UNION ALL

  SELECT e.id, e.event_type, e.started_at, e.metadata
  FROM codex.events_timeline e
  JOIN chain c
    ON c.id::text = ANY(
      ARRAY(SELECT jsonb_array_elements_text(e.metadata->'related_event_ids'))
    )
  WHERE e.started_at - c.started_at BETWEEN interval '0' AND interval '365 days'
)
SELECT * FROM chain
WHERE event_category = 'civic';

Confidence semantics

The confidence field represents pipeline confidence that the event is real, not a downstream prediction score:
  • Maritime — AIS signal quality × kinematic model posterior
  • Civic — LLM extraction confidence × source reliability score
  • Regulatory — 1.0 for primary-source filings; degraded for secondary mirrors
  • Environmental — satellite cloud cover × model confidence
Events with confidence < 0.4 are excluded from Research and Commercial tier exports by default.

Join keys

KeyPresenceNotes
event_id (= id)alwaysPrimary key — the spine across all Codex datasets
record_idalwaysAPRS URN: urn:aprs:record:event:{product}:{id}
chunk_idalwaysDeterministic from record_id
h3_indexoftenNull for events without geometry (e.g., regulatory filings)
jurisdiction_slugoftenAlways for civic and regulatory; sometimes for others
mmsimaritime onlyIn metadata.mmsi
imomaritime onlyIn metadata.imo (preferred over MMSI)
parcel_idcivic onlyIn metadata.parcel_id
entity_urnoftenPresent for person, organization, and POI entities

Example queries

Permit cascades after approved rezonings

SELECT
  rez.id             AS rezoning_event_id,
  rez.jurisdiction_slug,
  rez.started_at     AS rezoning_date,
  permit.event_type  AS permit_stage,
  permit.started_at  AS permit_date,
  permit.started_at - rez.started_at AS lag
FROM codex.events_timeline rez
JOIN codex.events_timeline permit
  ON permit.metadata->'related_event_ids' ? rez.id::text
WHERE rez.event_type = 'council.approved'
  AND rez.started_at >= now() - interval '1 year'
  AND permit.event_type LIKE 'permit.%'
ORDER BY rez.jurisdiction_slug, rez.started_at;

All dark events longer than 48 hours

SELECT
  entity_name,
  started_at,
  resolved_at,
  magnitude AS gap_hours,
  metadata->'kinematic_meta'->>'implied_speed_kn' AS implied_speed
FROM read_parquet('events-timeline-2026-04.parquet')
WHERE event_type = 'dark_event'
  AND magnitude > 48
ORDER BY magnitude DESC;

Known limitations

  • entity_id shape is polymorphic — you must branch on entity_type before joining.
  • magnitude units vary by event type. See magnitude units before comparing.
  • related_event_ids coverage is uneven. Currently populated by maritime and permit normalizers; civic cascade linking is in progress.
  • downstream_outcome is post-hoc and sparse — only populated once cascade detectors run, which can take 30–90 days.