CEEJAYDocs

SDK changelog

What changed in each version of the SDK, and how its versions are numbered.

Versions

One entry for each version, newest first, with its date and one line for each change. A line that starts with Breaking can stop code written for an older version from working.

0.1.0 - 2026-11-12

The first published version of the CEEJAY SDK for TypeScript.

  • One function for each of the 36 requests a studio's server makes, with types generated from the OpenAPI specification.
  • Connect, from your server: ceejay.connect.createPass, createSession, getSession, listSessions and confirmSession.
  • The players of a game, from your server: ceejay.players.get, list, disconnect, delete, setFields and logEvents, and the field map: ceejay.fieldMap.get and propose. ceejay.players.list returns the full response, with page. The six writes take no idempotency key.
  • The two events player.connected and player.disconnected are typed in WebhookEvent.
  • A 413 is given the code body_too_large, also when only a proxy responded.
  • Connect, inside a game: CeejayConnect, in @communitystudios/ceejay/connect. It stores the game's public key, starts a connect session, polls for the result, asks the game for the player's confirmation, and stores and renews the player session. It runs in a browser too.
  • A game can prove who its player is with a Firebase ID token, a Unity Player Authentication token or a Steam ticket (proof.type: firebase, unity or steam), or with a connect pass from your server.
  • Every function that grants, deducts or posts takes an idempotencyKey. A repeated request returns the original response, with duplicate: true. The three writes of Connect, the four writes of ceejay.players and ceejay.fieldMap.propose take none.
  • verifyWebhook and verifyDelivery check signature version 2 of what CEEJAY sends to your server, and say which delivery and which attempt it is. The legacy signature is accepted only with allowLegacy.
  • A read, and a write sent with an idempotency key, is retried after a 429, a 5xx or no response, and a write with a key also while the first request with that key is still running. A write without a key is never retried.
  • Every error has a code and a requestId.
  • Runs on Node 20 and later, Deno and edge functions, with no dependencies.

Which API version the first SDK version targets

Version 0.1.0 of the SDK targets version 1.1.0 of the CEEJAY API. If you call the API with code of your own today, this is what you see when you move to the SDK, or to this version of the API:

  • New: ceejay.community.get, ceejay.roles.list, ceejay.channels.list, ceejay.programs.list and ceejay.shop.listPurchases.
  • New: ceejay.quests.reportTask sends to an endpoint under /api/v1. The older endpoint keeps working.
  • New: Connect, which links a player of your game to their Discord account. From your own server: ceejay.connect.createPass, ceejay.connect.createSession, ceejay.connect.getSession, ceejay.connect.listSessions and ceejay.connect.confirmSession, with a key that has players:connect. From inside the game: CeejayConnect, in @communitystudios/ceejay/connect, with the game's public key.
  • New: the players of a game and its field map, from your server: ceejay.players.get, ceejay.players.list, ceejay.players.disconnect, ceejay.players.delete, ceejay.players.setFields and ceejay.players.logEvents, and ceejay.fieldMap.get and ceejay.fieldMap.propose. They need players:read, players:write, players:connect or players:delete, and none takes an idempotency key. The events player.connected and player.disconnected are typed in WebhookEvent.
  • New: the game loop, from inside the game. After a player is connected, connect.hub shows the community's quests, shop, locker, rank and daily reward: connect.hub.listQuests, startQuest, verifyQuestTask, answerQuestTask, listShop, buy, listLocker, claim, getRanks, getBalance and checkIn. connect.hub.buy sends every attempt with the same idempotencyKey, and a purchase blocked by a spending hold is a CeejaySpendBlockedError. The delivery CEEJAY signs for a purchase made in a game carries player, which ShopDelivery types.
  • New: every function that grants, deducts or posts takes an idempotencyKey. A repeated request returns the original response, with duplicate: true. The three writes of Connect, the four writes of ceejay.players and ceejay.fieldMap.propose take none, and are safe to retry as they are.
  • New: every response includes the key's rate limit and the remaining allowance in three headers, and carries the request ID, which an error exposes as requestId.
  • New: every error has a code.
  • New: every delivery carries X-CEEJAY-Signature-V2, with a time, a delivery ID and an attempt number, and verifyWebhook and verifyDelivery check it. The legacy signature is still sent.
  • New: each account in connections of ceejay.members.get carries proof: 'verified' or 'basic' for a connection to a game, null for any other account.
  • New names: playerId and playerName on a linked account, reason for the note on the two currency functions, taskKey and xHandle on a reported task. The API still accepts the older names. The SDK types include the new names only.
  • Changed: a quest completed with ceejay.quests.complete now gets the quest's role, the rewards of its reward list, program XP for a quest in a program, and the quest.completed event. If you added any of these yourself after each completion, stop: the member would get it twice.
  • Changed: ceejay.quests.complete applies the community's daily quest limit.
  • Changed: ceejay.quests.complete does not grant a quest's coins while the community's economy is switched off. The response includes currencySkipped: true. XP, the badge and the role are still granted.
  • Changed: a key's limit is at most 600 requests a minute.
  • Changed: with no content, ceejay.messages.send rejects embeds that is not a list.
  • Changed: ceejay.members.link needs the member to be in the server, and trims whitespace from playerId.
  • Changed: ceejay.quests.reportTask only touches quests whose task key matches, and completes a quest that needs a role only for a member who has it.

One rule from now on: within version 1 of the API nothing is renamed or removed.

How versions are numbered

A version has three numbers, such as 1.4.2.

The number that changesNameWhat it means for your code
The third, 1.4.2 to 1.4.3PatchWording and limits only. Nothing changed shape. Update when you like
The second, 1.4.2 to 1.5.0MinorSomething new: a function, an event, or a field you may leave out. Code written for the version before keeps working
The first, 1.4.2 to 2.0.0MajorSomething was removed or renamed, became required, or changed type. Read the entry before you update

Each line of an entry describes one change. A line that starts with Breaking is one that can stop older code from working.

Where the entries come from

The SDK is generated from the same OpenAPI specification as the API reference. When the specification changes, a script compares it with the specification of the last version and writes the entry from the differences. A change we wrote by hand, such as a faster retry, gets a line of its own.

The API has a changelog of its own

The API changes separately from the SDK, and its changes are documented on API changelog and versioning. Version 1 of the API adds requests, events and fields. It does not remove or rename them. So a major version of the SDK is not expected while the API is at version 1.

On this page

Community StudiosPrivacyTerms