CEEJAYDocs

TypeScript SDK

Call the CEEJAY API from your server with typed functions, and check the requests CEEJAY sends you.

The SDK has one function for each request in the API reference, with types generated from the same OpenAPI specification as the reference. It also checks the signature of a webhook or a shop delivery, and has a client for a game that links a player to their Discord account and shows the community's quests, shop and rank.

Install the SDK
npm install @communitystudios/ceejay

The npm package has no runtime dependencies. The quickstart covers installing the SDK and making your first request.

Two ways in

ImportIt is forIt uses
@communitystudios/ceejayYour serverYour secret key. Use it on a server only: never in a browser, a mobile app or a game client
@communitystudios/ceejay/connectYour gameThe game's public key, which is no secret. It rejects a secret key

The API reference shows each request the SDK sends as cURL and as TypeScript, so you can read either one beside the function it calls.

Create the client

Create an API key in the dashboard under Settings → Developers → API Keys. Grant it only the permissions it needs, and store it in an environment variable.

Create the client
import { Ceejay } from '@communitystudios/ceejay'

const ceejay = new Ceejay({ apiKey: process.env.CEEJAY_API_KEY })

A key belongs to one Discord server, so you never pass a server ID.

Prop

Type

What a function returns

A function returns what is inside data in the response. A function that lists returns the full response, with the list in data and page alongside it. So do quests.reportTask and shop.completePurchase, whose responses contain more than data.

Read a member and list quests
const member = await ceejay.members.get('409876543210987654')
console.log(member.displayName, member.level, member.economy.balance)

const page = await ceejay.quests.list({ limit: 20 })
console.log(page.total, page.data.map((quest) => quest.title), page.page.nextCursor)

Every function takes { signal, timeoutMs, maxRetries } as its last argument, for one call. Start with ceejay.community.get(): any valid key can call it, and it reports what the key can do and which features are enabled on your instance.

Write with an idempotency key

Every function that grants, deducts or posts takes an idempotencyKey in its options: all 14 of them. The key is a string you choose, 1 to 128 characters, for this one request. When the same request is sent again with its key, nothing is repeated: the response is the original one, with duplicate: true.

Grant currency with a key
const grant = await ceejay.economy.grant(
  { discordId: '409876543210987654', amount: 250, reason: 'Season prize' },
  { idempotencyKey: 'season-3-prize-409876543210987654' },
)

console.log(grant.amountGranted, grant.balance, grant.duplicate)

Use a new key for every separate request, and the same key only to retry one. Each key identifies one request: when one match grants coins and XP, send two keys, such as match-9:coins and match-9:xp. The three writes of ceejay.connect take none, because each is safe to retry as it is. Errors and retries has the rest.

Member IDs are strings

A Discord ID has 17 to 20 digits. A JavaScript number can hold only about 16 digits exactly, so an ID written as a number changes and refers to someone else. Always pass an ID in quotes.

A Discord ID is a string
await ceejay.members.get('409876543210987654') // right
// await ceejay.members.get(409876543210987654) // wrong: a number is refused, by the types and when it runs

Runtimes

  • Node 20 and later
  • Deno
  • Edge functions, such as Supabase Edge Functions

The SDK consists of ES modules and uses only fetch and Web Crypto. It imports no Node module. @communitystudios/ceejay/connect also runs in a browser, and uses fetch only.

All functions

One function for each of the 36 requests a studio's server makes. ceejay is the client from above. The permission is the one the API key needs: see Authentication for what each one allows.

FunctionRequestPermissionIdempotency key
ceejay.community.getGET /v1/communityany valid keyNo
ceejay.members.getGET /v1/members/{discordId}members:readNo
ceejay.members.linkPOST /v1/members/linkmembers:linkYes
ceejay.xp.getBalanceGET /v1/xp/balancexp:readNo
ceejay.xp.grantPOST /v1/xp/grantxp:grantYes
ceejay.xp.deductPOST /v1/xp/deductxp:deductYes
ceejay.xp.program.grantPOST /v1/xp/program/grantxp:program:grantYes
ceejay.xp.program.deductPOST /v1/xp/program/deductxp:program:deductYes
ceejay.programs.listGET /v1/programsprograms:readNo
ceejay.economy.getBalanceGET /v1/economy/balanceeconomy:readNo
ceejay.economy.grantPOST /v1/economy/granteconomy:grantYes
ceejay.economy.deductPOST /v1/economy/deducteconomy:deductYes
ceejay.quests.listGET /v1/quests/listquests:readNo
ceejay.quests.completePOST /v1/quests/completequests:completeYes
ceejay.quests.reportTaskPOST /v1/quests/tasks/completequests:completeYes
ceejay.roles.listGET /v1/rolesroles:manageNo
ceejay.roles.grantPOST /v1/roles/grantroles:manageYes
ceejay.roles.revokePOST /v1/roles/revokeroles:manageYes
ceejay.channels.listGET /v1/channelsmessages:sendNo
ceejay.messages.sendPOST /v1/messages/sendmessages:sendYes
ceejay.events.emitPOST /v1/events/emitevents:emitYes
ceejay.shop.listPurchasesGET /v1/shop/purchasesshop:fulfilNo
ceejay.shop.completePurchasePOST /v1/shop/purchases/{purchaseId}/completeshop:fulfilYes
ceejay.connect.createPassPOST /v1/games/{game}/connect/passesplayers:connectNo
ceejay.connect.createSessionPOST /v1/games/{game}/connect/sessionsplayers:connectNo
ceejay.connect.getSessionGET /v1/games/{game}/connect/sessions/{sessionId}players:connectNo
ceejay.connect.listSessionsGET /v1/games/{game}/connect/sessionsplayers:connectNo
ceejay.connect.confirmSessionPOST /v1/games/{game}/connect/sessions/{sessionId}/confirmplayers:connectNo
ceejay.players.getGET /v1/games/{game}/players/{playerId}players:readNo
ceejay.players.listGET /v1/games/{game}/playersplayers:readNo
ceejay.players.disconnectPOST /v1/games/{game}/players/{playerId}/disconnectplayers:connectNo
ceejay.players.deletePOST /v1/games/{game}/players/{playerId}/deleteplayers:deleteNo
ceejay.players.setFieldsPOST /v1/games/{game}/player-fieldsplayers:writeNo
ceejay.players.logEventsPOST /v1/games/{game}/player-eventsplayers:writeNo
ceejay.fieldMap.getGET /v1/games/{game}/field-mapplayers:readNo
ceejay.fieldMap.proposePOST /v1/games/{game}/field-map/proposeplayers:writeNo

A request that the API reference marks as a legacy endpoint of another request, such as the legacy endpoint of Complete a quest task, has no function: the SDK sends to the newer one.

Where to go next

On this page

Community StudiosPrivacyTerms