Reference

Client SDK and generated clients

One client library so far, in TypeScript and pre-release. For every other language we publish the machine-readable contracts, so you can generate a typed client and keep it in your own build — no dependency on our release cadence, no waiting for us to support your platform.

The TypeScript client #

@ollacore/client has two halves: typed REST for every operation in openapi.json, generated from the spec and checked against it on every release, and a room connection that does the part no generator produces — minting and renewing the session token through your server, reconnecting with backoff, catchup after a gap, dedupe by sequence, typing, and room.broadcast(body, to?) with the broadcast event. A refusal arrives on its error event.

Pre-release. It is not yet published to npm, and calls are not in it yet — the RTC socket and PeerConnection are still yours to write from Calls. Until it ships, the type-only generation below gives you the same request and response types.

The contracts #

FileFormatCovers
/openapi.json OpenAPI 3.1 All 114 HTTP operations. This is what generators consume.
/asyncapi.json AsyncAPI 3.1 The two WebSocket channels: chat and RTC signalling.
/ws-schemas.json JSON Schema WebSocket frame envelopes, referenced by the AsyncAPI document.
/api-examples.json Captured examples A real request and response for every one of the 114 operations.

All four are served with Access-Control-Allow-Origin: *, so browser tooling — Swagger UI, Redoc, Stoplight, an online generator — can fetch them directly by URL. (Until 2026-09-18 that was true of only three of them: api-examples.json was missing the header, and browser tooling fetching it cross-origin failed with an opaque network error.)

The OpenAPI document is kept in lockstep with the router by a parity check that fails our build: an endpoint cannot ship undocumented, and a documented endpoint cannot vanish. Every operation carries a stable operationId, which is what generators use to name methods.

TypeScript #

npx @openapitools/openapi-generator-cli generate \
  -i https://www.ollacore.com/openapi.json \
  -g typescript-fetch \
  -o ./ollacore

For most projects the lighter option is better — generate types and use your own fetch, rather than adopting a generated runtime:

# Types only — no runtime, no client. Often the better trade.
npx openapi-typescript https://www.ollacore.com/openapi.json -o ollacore.d.ts

Kotlin / Android #

npx @openapitools/openapi-generator-cli generate \
  -i https://www.ollacore.com/openapi.json \
  -g kotlin \
  -o ./ollacore \
  --additional-properties=library=jvm-okhttp4,serializationLibrary=kotlinx_serialization

Swift / iOS #

npx @openapitools/openapi-generator-cli generate \
  -i https://www.ollacore.com/openapi.json \
  -g swift5 \
  -o ./ollacore \
  --additional-properties=responseAs=AsyncAwait

Python #

npx @openapitools/openapi-generator-cli generate \
  -i https://www.ollacore.com/openapi.json \
  -g python \
  -o ./ollacore

Wiring up credentials #

// Four of the five planes are plain bearer tokens — the prefix tells you which:
//   ak_…   your server key        (server plane)
//   as_…   account session        (account plane)
//   du_…   directory session      (end-user plane)
//   eyJ…   room-scoped JWT        (client plane)
//
// Generated clients all expose some form of request interceptor. In
// typescript-fetch:
const api = new ServerApi(
  new Configuration({
    basePath: "https://api.ollacore.com",
    accessToken: () => process.env.OLLACORE_KEY,   // "ak_live_…"
  }),
);

The fifth plane, the operator control plane, is HMAC-signed rather than bearer-authenticated. Generators will emit its methods but not the signing, and you should not be calling it — it is deployment-wide and operator-only. See Authentication planes.

Generated type names will be uneven. Roughly a third of our request bodies and many response bodies are declared inline rather than as named components, so generators invent names like PostV1AccountSignupRequest for them. The methods and paths are correct and stable; the type names are not pretty. We're naming those schemas — it's mechanical work and it will improve generated output without changing the wire format.

WebSockets need hand-writing #

Chat delivery and call signalling run over WebSocket, and OpenAPI does not describe sockets — so no HTTP generator will produce that half of the client. It is deliberately a separate contract: asyncapi.json plus ws-schemas.json. In TypeScript the client's room connection is that half, for chat.

Written by hand, the socket client is small — one connection, a JSON envelope in each direction, a catchup on reconnect, and a rebuild of the PeerConnection on the RTC side after a 1001. Every frame type is documented with a real payload on WebSocket protocol. Budget an afternoon, not a sprint.

Mocking and contract tests #

api-examples.json holds a real, recorded request and response for all 114 operations — captured by driving a throwaway tenant through the live API, then redacted. Ids and timestamps are stable fixtures, so it is safe to assert against.

# Every operation's real request and response, keyed by operationId.
curl -s https://www.ollacore.com/api-examples.json \
  | jq '.operations.provisionRoom'

# → {
#     "method": "POST",
#     "path_template": "/v1/server/rooms",
#     "auth": "customer_key",
#     "request_body":  { "created_by": "alice", "external_ref": "order-7781" },
#     "response_status": 200,
#     "response_body": { "id": "0f5c…", "status": "active", … }
#   }

That makes it straightforward to stand up a mock server, or to write a contract test that fails when our response shape moves under you.

Postman #

/ollacore.postman_collection.json is the same corpus as a Postman collection, built with the site, so it always matches this reference. Import it by link (File → Import → Link).

  • A Quickstart folder that runs top to bottom: create an account, create a key, provision a room, add a member, mint a token, send, read the history.
  • Four reference folders, one per plane you call: account, server, client and directory, one request per operation. These follow the reference, not a runnable order — some requests delete what others create — so run their requests one at a time. The operator plane (HMAC-signed) is left out; you never need it.
  • Credentials are collection variables — as_session, ak_key, access_token, du_session — and every request names the one it uses. Sign up, log in, key creation and rotation, token minting and OTP verification fill them in for you, as do the requests that create a room, message, webhook or upload.
  • Every request carries its recorded response as a saved example, so Postman's mock server can stand in for the API while you build a client.

To start, set account_email and account_password in the collection's Variables tab and run the Quickstart folder. Keys are created in the test environment unless you set key_environment to live, so experiments never touch live data. For the directory, set phone, request a code, then set otp_code to the code that arrives before you verify. Path ids you have not created yet (a principal_id you choose, a delivery_id from the log) are empty variables: set them there too.