CEEJAYDocs

Quickstart

Create a key and make your first authenticated call in about two minutes.

Make your first call

Create an API key

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

Name the key after where it will run, such as Roblox game server or Staging worker. Full Access is ticked when the dialog opens. Tick only the scopes the key needs instead: ticking one clears Full Access. For this quickstart that is Members Read and XP Grant. Then press Generate, and the dialog closes.

The full key is shown once, in a banner above the list of keys that starts Copy your API key now. Copy it immediately into your secret manager; we store only a hash, so it cannot be recovered or displayed again. If you lose it, revoke it with the delete icon at the end of its row and generate a new one.

Make a request

Every request carries the key as a bearer token. Start with Community details, which any valid key can call. It returns which community the key belongs to, the scopes it has and what your instance supports:

Community details (cURL)
curl https://ceejay.communitystudios.xyz/api/v1/community \
  -H "Authorization: Bearer $CEEJAY_API_KEY"

The next one reads a member's profile. Use the Discord ID of a member of your community: a member CEEJAY has never seen returns 404.

The examples use the shared CEEJAY service, whose base URL is https://ceejay.communitystudios.xyz/api/v1. On a dedicated instance the base URL is your dashboard's URL followed by /api/v1: use the URL you see in your browser when you open your dashboard. See Base URL.

Read a member (cURL)
curl https://ceejay.communitystudios.xyz/api/v1/members/409876543210987654 \
  -H "Authorization: Bearer $CEEJAY_API_KEY"

Award something

Writes are POST with a JSON body. This grants 250 XP, and the grant is real, so use your own account or a test member. Send the Content-Type: application/json header with every JSON body: without it the body is not read as JSON, and the response is a 400. From curl -d it says discordId is invalid, as if you had left it out. From a client that sends no content type it says The request body must be a JSON object.

Grant XP (cURL)
curl -X POST https://ceejay.communitystudios.xyz/api/v1/xp/grant \
  -H "Authorization: Bearer $CEEJAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "discordId": "409876543210987654",
    "amount": 250,
    "reason": "Won the Saturday tournament",
    "idempotencyKey": "tournament-2026-w40-first-place"
  }'

The response shows what the member had before and after, and whether the grant levelled them up:

200 OK
{
  "success": true,
  "data": {
    "discordId": "409876543210987654",
    "previousXP": 8200,
    "xpGranted": 250,
    "totalXP": 8450,
    "previousLevel": 11,
    "currentLevel": 12,
    "leveledUp": true,
    "reason": "Won the Saturday tournament",
    "auditId": "1873",
    "xp": 8450,
    "previousXp": 8200,
    "level": 12,
    "duplicate": false
  }
}

xp, previousXp and level are the current field names. totalXP, previousXP and currentLevel return the same values under their legacy names, kept for backwards compatibility, and are still sent.

The idempotencyKey makes the call safe to retry: if it times out, retry with the same body and the same key, and the member receives the XP once. The second response is the original response, with duplicate: true. Every request that creates or changes data takes a key.

Keep keys server-side

An API key grants write access to your community. Never ship one in a browser bundle, mobile app or game client. Call the CEEJAY API from your own backend and let your client talk to that. The API does not accept calls from browsers on other websites.

  • Authentication lists every scope.
  • Rate limits and Errors say what to expect when a call fails.
  • Webhooks send you events instead of you polling for them.
  • The TypeScript SDK has a typed function for each request, and the reference pages show the TypeScript call beside the cURL one.

On this page

Community StudiosPrivacyTerms