Open gRPC / Protocol Buffer specification for the Extremo external partner API.
This repository is the source of truth for the public, externally-published surface of the Extremo booking platform — the API that third-party partners and integrations call. It is published as an open spec under Apache-2.0.
Status: early / v1 in progress. The surface is being built out under
threecorp/extremo-proto#50and the Phase E epicthreecorp/extremo-proto#26.
The Extremo internal protos live in a private monorepo. The external API is deliberately carved out here because:
- Anti-corruption boundary. This module has no dependency on the internal
extremo-protomodule, so it is impossible toimport "extremo/msg/db/v1/db.proto"(or any internal type) from these files —buf buildfails on an unknown import. Internal database shapes (foreign keys, soft-delete flags, audit timestamps, nested internal relations) can never leak into the public contract. The boundary is a CI-enforced invariant, not a convention. - Open spec. Partners can read the entire contract from one public repo, and Extremo ships the reference implementation (the "open core" / open-protocol playbook).
- Independent stability.
buf breakingon this repo gates the external API's v1 compatibility.
The external surface is authenticated (per-tenant API key + scopes) and distinct from the internal anonymous public/ booking-page services.
Each API key is granted a subset of these scopes; every RPC checks the scope it needs.
| Scope | Grants |
|---|---|
service.read |
Read the tenant's service catalog |
tenant.read |
Read the tenant's public profile |
availability.read |
Read computed booking availability |
book.read |
Read the tenant's bookings |
book_event.read |
Read the booking change feed |
book.create |
Create a booking for a consumer (CreateBooking) |
book.update |
Mutate a booking (UpdateBooking / CancelBooking) |
Booking writes (book.create / book.update) let a partner create, reschedule, and cancel bookings on a consumer's behalf: CreateBooking takes a Consumer{name, email?, phone?} and the platform resolves (or creates) the tenant's consumer record from it, validates the slot against the tenant's schedule (capacity / staff / no past times), and returns the booking. Supply an idempotency_key to make retries safe, and echo a booking's updated_at as expected_updated_at on UpdateBooking for optimistic concurrency (a mismatch returns ABORTED). Consumer contact details are never echoed back in a Booking — PII stays server-side.
extremo/
├── msg/external/v1/ # Public DTOs (Service, Booking, TenantProfile, AvailabilitySlot, Staff, enums)
└── api/external/<svc>/v1/ # External services (REST via google.api.http: /api/external/v1/...)
Generated SDKs:
externalgo/ # Go
externaltsnode/ # TypeScript (ES + TanStack Query)
lib/ # Dart
Requires buf and go (provided by the bundled nix flake via direnv):
direnv allow # first time
make lint # buf lint + build
make protocol # generate Go / TS / DartGo:
go get github.com/threecorp/extremo-external-proto@latestimport extsvc "github.com/threecorp/extremo-external-proto/externalgo/extremo/api/external/services/v1"(A Buf Schema Registry module — buf.build/threecorp/extremo-external — and Ruby / Python SDKs are planned for the reference client at threecorp/extremo-spec#7.)
- Strategy:
threecorp/extremo-spec#6(Phase E acceleration),#5(OSS carve-out) - Roadmap:
extremo-spec/ROADMAP.md§7