Contract

A source product reports its fact, the Calendar owns its schedule. Between them sits a narrow interface that does not grow with the number of integrations.

Event identity is a triple

Product, entity type and entity id. A product does not need to store an internal Calendar id: it addresses the event by what it already owns.

(product_id, entity_type, entity_id)
  • A repeated upsert on the same triple updates the record instead of creating a second one
  • A repeated remove after deletion is a no-op, not an error
  • Only the product that created the event with its own key can delete it
  • Detach tokens are unnecessary: an event has exactly one owning product

Contract endpoints

EndpointPurpose
POST /Calendar/upsertCreate or update a product event
POST /Calendar/removeDelete an event by its identity triple
GET /Calendar/listByEntityEvents of one product entity
GET /Calendar/eventsThe query behind personal and team views
GET /Calendar/freebusyAvailability of people and resources without details
GET /Calendar/expandExpansion of a recurrence into occurrences
POST /Calendar/findSlotsSearch for a shared free window
POST /Calendar/attachConferenceProvision an A3.Meet room for an event
POST /Calendar/invite, /Calendar/rsvpInvite a participant and record the answer
GET /Calendar/ics/{token}Read-only subscription for an external client

Transport conventions

  • Headers

    API_KEY, A3Session, AccountId, ProductId and Language-Code. A product call is authorised by the product key, a user call by the A3.ID session.

  • Response envelope

    One envelope with status, code, error text and payload. Errors arrive in the same envelope, already localised by Language-Code.

  • Lists

    Lists come back with a total count, while filtering and paging go through request filters.

  • Documentation

    Scalar and Swagger in six languages. CalDAV is documented separately: it is a protocol on top of WebDAV, not a JSON contract.

The event version resolves conflicts

Every update carries the version the caller last saw. If it has drifted from the current one, the server answers 409 with the current state. The conflict is resolved by the caller, not by the server.

409 Conflict
  • For a product the usual handling is a retry with the new version: it owns the field outright
  • For a person a comparison dialog is shown with a choice of which version to keep
  • The same version doubles as the CalDAV ETag: there is no second mechanism
  • This is neither CRDT nor write locks: the model matches the real load profile

More than REST

  • CalDAV

    A separate path by RFC 4791 with methods for calendar discovery, range queries, writes and deletes. A product event is visible, but writing to it is rejected.

  • Live channel

    A change journal with a monotonic cursor plus a realtime hub. An open tab updates immediately, an offline client catches up through the same cursor.

  • Widget

    An embeddable frame over the event and availability queries, for a product that needs a grid inside its own interface. The frame opens with a short-lived token from the product server.

  • Limits

    A write rate limit per product and a request log for non-default keys, so incidents can be reconstructed.

Integration permissions

An integration does not get access to the whole company calendar without an explicit grant from the account owner.

  • ReadReceive events
  • PushCreate and update its own events
  • FreeBusyQuery availability without event details
  • ShareManage shared access to calendars

Open the documentation

The full description of endpoints, models and error codes in six languages.