Maintainer: Sam Benson — GitHub
Contact: sam@acespec.dev
Base Format: JSCalendar (RFC 8984)
Media Type: application/ace+json
Status: Draft 0.1
License: CC BY 4.0
The Active Calendar Events (ACE) specification defines a consistent, verifiable way to publish and update calendar events in real time.
ACE extends JSCalendar by introducing:
- Versioning — sequential updates with referential continuity.
- Verification — JSON Web Signatures (JWS) to ensure authenticity.
- Delivery — webhook-based notifications for live change propagation.
Each ACE message wraps a valid JSCalendar object in a signed ACE Envelope.
Implementations are transport-agnostic but MUST conform to the envelope and signature rules below.
| Property | Description |
|---|---|
| Base Type | Every ACE payload is a valid JSCalendar object. |
| Media Type | application/ace+json |
| Extension Model | Additional ACE fields appear in a separate envelope, not inside JSCalendar. |
| Compatibility | Converting between ACE and JSCalendar MUST be loss-free. |
An ACE Envelope encapsulates the current state or update of an event, including metadata, version information, and optional detached JWS signature.
| Field | Type | Required | Description |
|---|---|---|---|
spec |
string | ✅ | Specification identifier (e.g. "ACE/0.1"). |
publisher |
string (URI) | ✅ | Canonical base URL of the publishing service. |
version |
integer | ✅ | Monotonic version number incremented on each update. |
issued_at |
string (date-time) | ✅ | UTC timestamp when this version was issued. |
event |
object (JSCalendar) | ✅ | Valid JSCalendar event payload. |
sig |
object | ✅ | JWS signature metadata and payload (see § 3.3). |
type |
string | ❌ | "diff" for partial updates; "full" or omitted for complete events. |
baseVersion |
integer | ❌ | Version number upon which this update is based (required if type="diff"). |
diff |
object | ❌ | Partial update map describing changes relative to baseVersion. |
reason |
string | ❌ | Human-readable reason for the update (e.g. "Room conflict"). |
meta |
object | ❌ | Optional implementation-specific metadata. |
{
"spec": "ACE/0.1",
"publisher": "https://example.com",
"version": 3,
"issued_at": "2025-11-03T12:12:00Z",
"event": {
"@type": "jsevent",
"uid": "9f2b1@example.com",
"title": "Design Review",
"start": "2025-11-04T15:00:00Z",
"duration": "PT30M"
},
"sig": {
"alg": "EdDSA",
"kid": "https://example.com/.well-known/ace.jwks#key1",
"jws": "eyJhbGciOiJFZERTQSIsImtpZCI6ImtleTEifQ..."
}
}{
"spec": "ACE/0.1",
"type": "diff",
"publisher": "https://example.com",
"version": 3,
"baseVersion": 2,
"issued_at": "2025-11-03T13:00:00Z",
"diff": {
"event.title": "Design Review (final)",
"event.start": "2025-11-04T15:30:00Z"
},
"reason": "Room conflict",
"sig": {
"alg": "EdDSA",
"kid": "https://example.com/.well-known/ace.jwks#key1",
"jws": "eyJhbGciOiJFZERTQSIsImtpZCI6ImtleTEifQ..."
}
}The sig object conveys signature and verification data following RFC 7515 (JWS).
| Field | Type | Required | Description |
|---|---|---|---|
alg |
string | ✅ | The JWS algorithm. ACE v0.1 MUST use EdDSA; ES256 MAY be supported. |
kid |
string (URI) | ✅ | Key identifier pointing to a JWKS resource or fragment. |
jws |
string | ✅ | Compact detached JWS signature over the canonicalised event object. |
Canonicalisation:
Implementations MUST apply RFC 8785 (JSON Canonicalisation Scheme) to the event object prior to signing.
Verification Steps:
- Retrieve the publisher’s public key from
kid. - Canonicalise the
event. - Verify the JWS.
- Accept only if the signature is valid and
versionis greater than or equal to the previously known version.
- Each envelope represents one immutable, authoritative state of an event.
- Publishers MUST increment
versionmonotonically. - Receivers SHOULD store previous versions for reconciliation and audit.
- Partial updates (
type="diff") MUST reference a validbaseVersion. - The envelope structure is transport-agnostic and MAY be distributed via any mechanism defined in § 6.
ACE does not mandate a transport layer. Implementations MAY deliver envelopes through HTTP, Webhooks, or WebSub.
- A subscriber registers via
POST /subscribewith its callback URL. - The publisher stores the subscription and begins sending POST requests containing ACE envelopes.
- Subscribers respond with HTTP 200 OK to acknowledge. Failed deliveries SHOULD be retried with exponential backoff.
Clients periodically GET /events/{uid} to check for updates. If version or ETag differs, the latest envelope is returned.
Publishers SHOULD expose discovery metadata at:
https://<domain>/.well-known/ace.json
Example:
{
"organization": "Example Corp Calendar",
"publicKey": "base64-ed25519-public-key",
"schema": "https://acespec.dev/schema/v0.1"
}An implementation is ACE 0.1-compliant if it:
- Emits valid ACE envelopes containing valid JSCalendar objects.
- Implements version monotonicity and signature verification as specified.
- Recognises and supports
application/ace+jsoncontent.
- Recurrence sets and series relationships
- Publisher federation and multi-tenant feeds
- WebSub profile for real-time delivery
- Encryption and selective disclosure metadata
| Version | Date | Summary |
|---|---|---|
| 0.1 (Draft) | 2025-11-03 | Initial draft: envelope, versioning, signatures, and transport defined. |
© 2025 Sam Benson. Released under CC BY 4.0.