CEEJAYDocs

SDK quickstart

Install the SDK, make your first call and handle a refusal in about five minutes.

The SDK is for your own server. It uses your secret key, so never use it in a browser, a mobile app or a game client. Your client should call your server, and your server should call CEEJAY.

What you need

  • Node 20 or later, Deno, or an edge function such as a Supabase Edge Function.
  • An API key from the CEEJAY dashboard. Step 2 makes one.
  • The Discord ID of a member of your community, to try the calls on. Use your own.

Make your first call

Install the SDK

Install the SDK (npm)
npm install @communitystudios/ceejay

The SDK has no dependencies of its own.

Create an API key

In the CEEJAY dashboard open Settings → Developers → API Keys and click Generate Key.

Name the key after where it will run. Full Access is ticked when the dialog opens. Tick only the permissions the key needs instead. For this quickstart that is Members Read and XP Grant. Then click Generate.

The full key is shown once. Copy it into an environment variable on your server, here CEEJAY_API_KEY. If you lose it, revoke it and generate a new one.

Create the client

Create the client (Node)
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. In a Supabase Edge Function, read the key with Deno.env.get as well.

On a dedicated CEEJAY instance, also pass the base URL of your dashboard. See Dedicated instances.

Ask what the key can do

Any valid key can make this call, whatever its permissions, so it is a good first one. It returns which community the key belongs to, what the key may do, and which features this instance has enabled.

Community details (TypeScript)
const community = await ceejay.community.get()

console.log(community.name, community.key.scopes, community.key.rateLimitPerMinute)
console.log(community.features.quests.available, community.features.retryKeys.available)

Read a member

Read a member (TypeScript)
const member = await ceejay.members.get('409876543210987654')

console.log(member.displayName, member.level, member.economy.balance)

Pass a Discord ID as a string, in quotes. An ID has 17 to 20 digits, and a JavaScript number cannot hold that many: its last digits change and it identifies someone else. The SDK rejects a number at compile time and at runtime.

If CEEJAY has no profile for the member, the request fails with status 404 and the code member_not_found.

Give XP

This call grants real XP, so use your own account or a test member.

Give XP (TypeScript)
const grant = await ceejay.xp.grant(
  { discordId: '409876543210987654', amount: 250, reason: 'Won the Saturday tournament' },
  { idempotencyKey: 'saturday-cup-2026-41:xp' },
)

console.log(grant.xp, grant.level, grant.leveledUp, grant.duplicate)

The second argument contains an idempotency key: a string you choose for this one request. If the same request is sent again with the same key, the XP is not granted a second time, and the response is the original one with duplicate: true. With a key, the SDK retries automatically after a failure. Without one it never retries. Every function that grants, deducts or posts accepts a key. See Errors and retries.

Handle a refusal

A request CEEJAY refuses throws a CeejayError. A request that receives no response throws a CeejayConnectionError.

Handle a refusal (TypeScript)
import { CeejayConnectionError, CeejayError } from '@communitystudios/ceejay'

try {
  await ceejay.xp.grant({ discordId: '409876543210987654', amount: 250 })
} catch (error) {
  if (error instanceof CeejayError) {
    console.log(error.status, error.code, error.message, error.requestId)
  } else if (error instanceof CeejayConnectionError) {
    console.log('No answer from CEEJAY', error.timedOut)
  } else {
    throw error
  }
}

Where to go next

On this page

Community StudiosPrivacyTerms