Контракт

Продукт-источник сообщает о своём факте, Календарь отвечает за его расписание. Между ними узкий интерфейс, который не растёт вместе с числом интеграций.

Идентичность события это тройка

Продукт, тип сущности и её идентификатор. Внутренний идентификатор Календаря продукту хранить не нужно: он адресует событие тем, чем уже владеет.

(product_id, entity_type, entity_id)
  • Повторный upsert по той же тройке обновляет запись, а не создаёт вторую
  • Повторный remove после удаления это не ошибка, а пустая операция
  • Удалить событие может только продукт, создавший его своим ключом
  • Токены отвязки не нужны: у события ровно один продукт-владелец

Точки контракта

МетодНазначение
POST /Calendar/upsertСоздать или обновить событие продукта
POST /Calendar/removeУдалить событие по идентификационной тройке
GET /Calendar/listByEntityСобытия конкретной сущности продукта
GET /Calendar/eventsВыборка для личного и командного представления
GET /Calendar/freebusyЗанятость сотрудников и ресурсов без деталей
GET /Calendar/expandРазворот повторения в конкретные вхождения
POST /Calendar/findSlotsПодбор общего свободного окна
POST /Calendar/attachConferenceСоздание комнаты A3.Meet для события
POST /Calendar/invite, /Calendar/rsvpПриглашение участника и его ответ
GET /Calendar/ics/{token}Подписка внешнего клиента только на чтение

Транспортные конвенции

  • Заголовки

    API_KEY, A3Session, AccountId, ProductId и Language-Code. Продуктовый вызов авторизуется ключом продукта, пользовательский сессией A3.ID.

  • Конверт ответа

    Единый конверт со статусом, кодом, текстом ошибки и полезной нагрузкой. Ошибки приходят в нём же и уже локализованы по Language-Code.

  • Списки

    Списки возвращаются вместе с общим числом записей, фильтрация и постраничность идут через фильтры запроса.

  • Документация

    Scalar и Swagger на шести языках. CalDAV описан отдельно: это не JSON-контракт, а протокол поверх WebDAV.

Версия события решает конфликты

Каждое обновление передаёт версию, которую вызывающая сторона видела последней. Если она разошлась с текущей, сервер отвечает кодом 409 и актуальным состоянием. Конфликт решает вызывающая сторона, а не сервер.

409 Conflict
  • Продукту типовая обработка это повтор с новой версией: он владеет полем целиком
  • Человеку показывается диалог сравнения версий с выбором, какую оставить
  • Та же версия служит ETag протокола CalDAV, второго механизма нет
  • Это не CRDT и не блокировки на запись: модель соразмерна реальной нагрузке

Не только REST

  • CalDAV

    Отдельный путь по RFC 4791 с методами обнаружения календарей, выборки по диапазону, записи и удаления. Событие продукта видно, но запись в него отклоняется.

  • Живой канал

    Журнал изменений с монотонным курсором плюс хаб реального времени. Открытая вкладка обновляется сразу, офлайн-клиент догоняет по тому же курсору.

  • Виджет

    Встраиваемый кадр поверх выборки событий и занятости для продукта, которому нужна сетка внутри своего интерфейса. Кадр открывается по короткоживущему токену от сервера продукта.

  • Ограничения

    Ограничение частоты на запись по продукту и журнал запросов недефолтных ключей для разбора инцидентов.

Права интеграции

Интеграция не получает доступ ко всему календарю компании без явного разрешения владельца аккаунта.

  • ReadПолучать события
  • PushСоздавать и обновлять свои события
  • FreeBusyЗапрашивать занятость без деталей события
  • ShareУправлять общим доступом к календарям

Открыть документацию

Полное описание точек, моделей и кодов ошибок на шести языках.