Skip to content

CDS v0.2.0 Specification

Status: Draft Issuer: SignedData.Org License: MIT Supersedes: CDS v0.1.0

The Curated Data Standard (CDS) is an open standard for distributing curated, cryptographically signed, real-time data from verified sources. Version 0.2.0 converts all identities — events, sources, content types — to dereferenceable HTTP URIs, making every CDS event valid JSON-LD. With this change, every CDS event becomes 5-star Linked Data: machine-readable, openly licensed, structured in a non-proprietary format, described using W3C standards, and linked to other people’s data via URIs.

Key properties of a CDS event remain unchanged:

  • Typed — carries a content_type URI identifying the domain and schema
  • Signed — RSA-PSS SHA-256 signature by the producer, verifiable by any consumer
  • Fingerprinted — SHA-256 of the raw upstream API response, proving source bytes were not altered
  • Enriched — optional LLM-generated context.summary in the declared language
  • Linked — every entity is a dereferenceable HTTP URI returning JSON-LD (NEW in v0.2.0)

CDS v0.2.0 is designed to satisfy the four Linked Data rules articulated by Tim Berners-Lee.

Rule 1: Use URIs as names for things. CDS names every entity with a URI. Events are identified by https://signed-data.org/events/{uuid}, content types by https://signed-data.org/vocab/{domain}/{schema}, and sources by https://signed-data.org/sources/{source-id}.

Rule 2: Use HTTP URIs so people can look up those names. All CDS URIs use the https://signed-data.org base. They are not opaque identifiers — they are HTTPS URIs that resolve to real endpoints on the web.

Rule 3: When someone looks up a URI, provide useful information using standards. Every CDS URI returns a JSON-LD document. Source URIs return source metadata; content type URIs return schema definitions; the vocabulary root returns the full ontology.

Rule 4: Include links to other URIs. CDS events contain links to other CDS resources — events to sources to domains to vocabulary, forming a navigable graph.

See Linked Data for the deep-dive.

CDS v0.2.0 achieves the maximum 5-star open data rating:

★ Available online under an open license ✓ (v0.1.0)
★★ Structured data (not a scanned image) ✓ (v0.1.0)
★★★ Non-proprietary format (JSON) ✓ (v0.1.0)
★★★★ Use open W3C standards (JSON-LD) ✓ NEW in v0.2.0
★★★★★ Link to other people's data (URI links) ✓ NEW in v0.2.0

Every CDS v0.2.0 event is a valid JSON-LD document:

{
"@context": "https://signed-data.org/contexts/cds/v1.jsonld",
"@type": "https://signed-data.org/vocab/CuratedDataEvent",
"@id": "https://signed-data.org/events/a3f8c2d1-4e2b-4f8a-9c1d-2e3f4a5b6c7d",
"spec_version": "0.2.0",
"id": "a3f8c2d1-4e2b-4f8a-9c1d-2e3f4a5b6c7d",
"content_type": "https://signed-data.org/vocab/lottery-brazil/mega-sena-result",
"source": {
"@id": "https://signed-data.org/sources/caixa.gov.br.loterias.v1",
"fingerprint": "sha256:b310..."
},
"occurred_at": "2026-03-29T00:00:00Z",
"ingested_at": "2026-03-29T00:00:04Z",
"lang": "pt-BR",
"payload": { },
"context": {
"summary": "Mega Sena concurso 2800...",
"model": "rule-based-v1",
"generated_at": "2026-03-29T00:00:05Z"
},
"integrity": {
"hash": "sha256:a1b2c3...",
"signature": "MX6rj3...",
"signed_by": "https://signed-data.org"
}
}

The @context, @type, and @id fields MUST appear first in serialised output. The id field (plain UUID) is retained alongside @id (full URI) for convenience.

Fieldv0.1.0v0.2.0Change
@contextabsent"https://signed-data.org/contexts/cds/v1.jsonld"new
@typeabsent"https://signed-data.org/vocab/CuratedDataEvent"new
@idabsent"https://signed-data.org/events/{uuid}"new
spec_version"0.1.0""0.2.0"bumped
content_typeCDSContentType objectURI stringbreaking
source.idopaque stringabsentremoved
source.@idabsentHTTP URIreplaces source.id
integrity.signed_by"signed-data.org""https://signed-data.org"breaking

All CDS URIs share the base https://signed-data.org.

ResourcePatternExample
Event/events/{uuid}https://signed-data.org/events/a3f8c2d1-...
Content type/vocab/{domain-slug}/{schema-slug}.../vocab/lottery-brazil/mega-sena-result
Source/sources/{source-id}.../sources/caixa.gov.br.loterias.v1
Vocabulary root/vocab/https://signed-data.org/vocab/
JSON-LD context/contexts/cds/v1.jsonld.../contexts/cds/v1.jsonld
Public key/.well-known/cds-public-key.pem.../cds-public-key.pem

Domain slugs: dots in the domain name become hyphens. lottery.brazillottery-brazil. sports.footballsports-football.

Schema slugs: dots in the schema name become hyphens. mega-sena.resultmega-sena-result.

Source IDs: dots are kept as-is. caixa.gov.br.loterias.v1 stays caixa.gov.br.loterias.v1.

https://signed-data.org/vocab/{domain-slug}/{schema-slug}

The builder function signature is content_type_uri(domain, schema_name) — both arguments use the original dot notation.

ConstantURI
LOTTERY_MEGA_SENA.../vocab/lottery-brazil/mega-sena-result
LOTTERY_LOTOFACIL.../vocab/lottery-brazil/lotofacil-result
LOTTERY_QUINA.../vocab/lottery-brazil/quina-result
LOTTERY_LOTOMANIA.../vocab/lottery-brazil/lotomania-result
LOTTERY_DUPLA_SENA.../vocab/lottery-brazil/dupla-sena-result
ConstantURI
FOOTBALL_MATCH_RESULT.../vocab/sports-football/match-result
FOOTBALL_MATCH_LIVE.../vocab/sports-football/match-live
FOOTBALL_STANDINGS.../vocab/sports-football/standings-update
ConstantURI
WEATHER_CURRENT.../vocab/weather/forecast-current
WEATHER_DAILY.../vocab/weather/forecast-daily
WEATHER_ALERT.../vocab/weather/alert-severe
ConstantURI
FINANCE_STOCK.../vocab/finance/quote-stock
FINANCE_CRYPTO.../vocab/finance/quote-crypto
FINANCE_FOREX.../vocab/finance/quote-forex
FINANCE_INDEX.../vocab/finance/index-update

See the finance.brazil domain spec for the full Brazilian finance content types.

A source represents a verified upstream data provider. Each source is identified by a URI of the form https://signed-data.org/sources/{source-id}.

Dereferencing a source URI returns a JSON-LD document:

{
"@context": "https://signed-data.org/contexts/cds/v1.jsonld",
"@type": "https://signed-data.org/vocab/DataSource",
"@id": "https://signed-data.org/sources/caixa.gov.br.loterias.v1",
"name": "Caixa Econômica Federal — Loterias",
"domain": "caixa.gov.br",
"version": "v1",
"upstream": "https://servicebus2.caixa.gov.br/portaldeloterias/api/megasena",
"content_types": [
"https://signed-data.org/vocab/lottery-brazil/mega-sena-result",
"https://signed-data.org/vocab/lottery-brazil/lotofacil-result"
]
}
ConstantSource URI
CAIXA_LOTERIAS.../sources/caixa.gov.br.loterias.v1
API_FOOTBALL.../sources/api-football.com.v3
OPEN_METEO.../sources/open-meteo.com.v1
BRAPI.../sources/brapi.dev.v1
BCB_SGS.../sources/api.bcb.gov.br.v1
CONAB.../sources/conab.gov.br.v1
WORLD_BANK.../sources/api.worldbank.org.v2
BRASILAPI.../sources/brasilapi.com.br.v1

The CDS ontology is published at https://signed-data.org/vocab/. It defines the classes and properties used in CDS events.

ClassURIDescription
CuratedDataEvent.../vocab/CuratedDataEventThe top-level event envelope
IntegrityMeta.../vocab/IntegrityMetaCryptographic proof attached to an event
DataSource.../vocab/DataSourceA registered upstream data provider
PropertyURIDomainRange
specVersion.../vocab/specVersionCuratedDataEventxsd:string
contentType.../vocab/contentTypeCuratedDataEventURI
source.../vocab/sourceCuratedDataEventDataSource
occurredAt.../vocab/occurredAtCuratedDataEventxsd:dateTime
ingestedAt.../vocab/ingestedAtCuratedDataEventxsd:dateTime
lang.../vocab/langCuratedDataEventxsd:string
payload.../vocab/payloadCuratedDataEventJSON object
context.../vocab/contextCuratedDataEventJSON object
hash.../vocab/hashIntegrityMetaxsd:string
signature.../vocab/signatureIntegrityMetaxsd:string
signedBy.../vocab/signedByIntegrityMetaURI
fingerprint.../vocab/fingerprintDataSourcexsd:string
  1. Serialise to canonical JSON — sort_keys=True, UTF-8, excluding integrity and ingested_at
  2. hash = "sha256:" + SHA256(canonical_bytes).hexdigest()
  3. Sign canonical_bytes with RSA-PSS (SHA-256 digest, MGF1, max salt length)
  4. Encode signature as base64
  5. Attach IntegrityMeta { hash, signature, signed_by }

Verification: re-serialise canonical bytes, check hash, verify RSA-PSS signature with the issuer public key published at https://signed-data.org/.well-known/cds-public-key.pem.

For full details, see Signing.

The @context at https://signed-data.org/contexts/cds/v1.jsonld maps the snake_case JSON keys used by CDS to RDF predicates:

{
"@context": {
"@vocab": "https://signed-data.org/vocab/",
"spec_version": "specVersion",
"content_type": { "@id": "contentType", "@type": "@id" },
"source": { "@id": "source", "@type": "@id" },
"occurred_at": "occurredAt",
"ingested_at": "ingestedAt",
"signed_by": { "@id": "signedBy", "@type": "@id" },
"fingerprint": "fingerprint",
"lang": "lang",
"payload": "payload",
"context": "context",
"hash": "hash",
"signature": "signature",
"integrity": "integrity"
}
}

This achieves two goals simultaneously:

  1. Plain JSON consumers are unaffected. A consumer that ignores @context, @type, and @id reads all other fields exactly as before. No JSON-LD library required.
  2. RDF consumers get valid triples. A JSON-LD processor expands any CDS event into an RDF graph. Fields typed as @id produce proper RDF links.
Changev0.1.0v0.2.0Impact
content_type field typeCDSContentType objectURI stringAll code that reads content_type.domain must change
source.id renamed to source.@idopaque stringHTTP URIJSON key change; use SDK helpers
integrity.signed_by"signed-data.org""https://signed-data.org"String comparison will break
Canonical bytesExclude integrity, ingested_atSame exclusions, but include @context, @type, @idv0.1.0 signatures cannot be verified by v0.2.0 verifiers
New required fieldsN/A@context, @type, @idProducers must include these fields

For migration code examples, see Migration v0.1 → v0.2.