CEEJAYDocs

ceejay.xp

Read, grant and deduct a member's XP, for the whole server or inside a community program.

Every function takes the same last argument, options: signal, timeoutMs and maxRetries, for that one call. A write also takes idempotencyKey there. Every function can also raise the errors any request can raise, such as a bad key or the rate limit. See Errors and retries.

Send each of the four writes on this page with an idempotencyKey. A grant that is sent again with the same key is not granted a second time, and the SDK then retries automatically after a failure. Without a key the SDK never sends a write twice: after a failure, read the member's total with ceejay.xp.getBalance before you decide to retry.

ceejay.xp.getBalance

Returns a member's total XP and level, without the rest of their profile.

GET /v1/xp/balance · requires xp:read · API reference: Get XP balance

Retried by the SDK: Yes. It is a read

Parameters

Prop

Type

Returns Schemas['XpBalanceResult'].

Prop

Type

Errors

This request has no errors specific to it. A member CEEJAY has not seen is not an error: xp and level are 0.

Example

ceejay.xp.getBalance
const balance = await ceejay.xp.getBalance('409876543210987654')

console.log(balance.xp, balance.level)

ceejay.xp.grant

Grants XP to a member. The response shows whether the member reached a new level.

POST /v1/xp/grant · requires xp:grant · API reference: Grant XP

Retried by the SDK: Only with idempotencyKey

Parameters: one object, then options.

Prop

Type

Options

Prop

Type

Returns Schemas['GrantXpResult'].

Prop

Type

The response also includes three legacy field names, which are still sent: totalXP (same as xp), previousXP (same as previousXp) and currentLevel (same as level).

When the grant raises the member to a new level, CEEJAY grants that level's rewards and level roles asynchronously, shortly afterwards. The request does not wait for them.

Errors

StatuscodeWhen
400bad_requestA field is missing or not valid, amount is above 100,000, or reason is not a string
404member_not_foundCEEJAY has no profile for this ID, and Discord reports that it is not in your server. A member who has just joined may not be available for up to 15 seconds: retry after 15 seconds
409xp_limit_reachedThe grant would exceed the maximum value CEEJAY can store for a member's XP. Nothing was granted
503discord_unavailableCEEJAY has no profile for this ID and could not check the member with Discord. Nothing was granted. The SDK retries if you sent a key

Idempotency errors are covered in Errors and retries.

Example

ceejay.xp.grant
const grant = await ceejay.xp.grant({
  discordId: '409876543210987654',
  amount: 250,
  reason: 'Won the Saturday tournament',
})

if (grant.leveledUp) {
  console.log(`Level ${grant.previousLevel} to level ${grant.level}`)
}

With a key, you or the SDK can safely retry the same grant:

ceejay.xp.grant with a key
const grant = await ceejay.xp.grant(
  { discordId: '409876543210987654', amount: 250, reason: 'Won match 881' },
  { idempotencyKey: 'match-881:xp' },
)

console.log(grant.duplicate ? 'Already given' : `Now at ${grant.xp} XP`)

ceejay.xp.deduct

Deducts XP from a member. The total never goes below 0: deducting more than the member has leaves them at 0.

POST /v1/xp/deduct · requires xp:deduct · API reference: Deduct XP

Retried by the SDK: Only with idempotencyKey

Parameters: one object, then options.

Prop

Type

Options

Prop

Type

Returns Schemas['DeductXpResult'].

Prop

Type

The response also includes three legacy field names, which are still sent: totalXP (same as xp), previousXP (same as previousXp) and currentLevel (same as level).

Errors

StatuscodeWhen
400bad_requestA field is missing or not valid, or reason is not a string
404member_not_foundCEEJAY has no profile for this member. Unlike a grant, a deduction never creates one, and does not check with Discord

Idempotency errors are covered in Errors and retries.

Example

ceejay.xp.deduct
const deduction = await ceejay.xp.deduct({
  discordId: '409876543210987654',
  amount: 100,
  reason: 'Left the match early',
})

console.log(deduction.xpDeducted, deduction.xp)

ceejay.xp.program.grant

Grants XP to a member inside a community program, such as an ambassador program. Program XP is tracked separately from the member's server XP.

POST /v1/xp/program/grant · requires xp:program:grant · API reference: Grant program XP

Retried by the SDK: Only with idempotencyKey

Parameters: one object, then options.

Prop

Type

Options

Prop

Type

The program must be active, and the member must be in it.

Returns Schemas['GrantProgramXpResult'].

Prop

Type

The response also includes two legacy field names, which are still sent: totalXP (same as programXp) and previousXP (same as previousProgramXp).

Errors

StatuscodeWhen
400bad_requestA field is missing or not valid, or reason is not a string
404program_not_foundThere is no program with this ID on your server
404member_not_enrolledThe member is not in the program
404member_not_foundThe ID is in the program, but is not a member of your server
404not_availablePrograms are not available on this instance
409program_not_activeThe program is not active. error.body includes the program's status as programStatus
409member_status_not_allowedThe member's status in the program does not allow XP changes. error.body includes it as memberStatus
409xp_limit_reachedThe grant would exceed the maximum value CEEJAY can store for a member's program XP
503discord_unavailableCEEJAY could not check this ID with Discord. Nothing was changed

Idempotency errors are covered in Errors and retries.

Example

ceejay.xp.program.grant
const grant = await ceejay.xp.program.grant(
  {
    programId: 3,
    discordId: '409876543210987654',
    amount: 500,
    reason: 'Hosted a community night',
  },
  { idempotencyKey: 'community-night-2026-10-03:409876543210987654' },
)

console.log(grant.programName, grant.programXp)

ceejay.xp.program.deduct

Deducts XP from a member inside a community program. The total never goes below 0.

POST /v1/xp/program/deduct · requires xp:program:deduct · API reference: Deduct program XP

Retried by the SDK: Only with idempotencyKey

Parameters: one object, then options.

Prop

Type

Options

Prop

Type

Returns Schemas['DeductProgramXpResult'].

Prop

Type

The response also includes two legacy field names, which are still sent: totalXP (same as programXp) and previousXP (same as previousProgramXp).

Errors

StatuscodeWhen
400bad_requestA field is missing or not valid, or reason is not a string
404program_not_foundThere is no program with this ID on your server
404member_not_enrolledThe member is not in the program
404not_availablePrograms are not available on this instance
409program_not_activeThe program is not active. error.body includes the program's status as programStatus
409member_status_not_allowedThe member's status in the program does not allow XP changes. error.body includes it as memberStatus
409xp_limit_reachedThe change would exceed the maximum value CEEJAY can store

Idempotency errors are covered in Errors and retries.

Example

ceejay.xp.program.deduct
const deduction = await ceejay.xp.program.deduct({
  programId: 3,
  discordId: '409876543210987654',
  amount: 50,
})

console.log(deduction.xpDeducted, deduction.programXp)

On this page

Community StudiosPrivacyTerms