← About
Developers · API

Plugin API: connect your game server

Connect your game server (Minecraft, Rust, ARK…) to your campaign: progress shows up in-game and rewards are granted automatically.

1. Authentication

Generate a key

In your dashboard: Campaign → Edit tab → “In-game plugin” → Generate a key. The full key (ka_live_…) is shown only once: copy it and paste it into your plugin config.

  • A key is scoped to a single campaign / a single server.
  • Only the SHA-256 hash is stored: nobody can read your key back. Lost it? Generate a new one.
  • You can revoke a key at any time; it stops working immediately.

Use the key

Send the key in the Authorization header of every request:

header
Authorization: Bearer ka_live_xxxxxxxxxxxxxxxxxxxxxxxx

Security: the key is a server secret. Never put it in a game client, a public repo, or anything players can access.

2. Basics

Base URLhttps://keepalive.gg · local dev http://localhost:3100
FormatJSON for requests and responses.
Rate limit~120 requests / minute per key. Beyond that → 429.
PollingAn interval of 30 to 60 s is plenty.

Errors follow a standard envelope: { "error": { "code", "message" } }

  • 401Missing, invalid or revoked key.
  • 404The campaign no longer exists.
  • 429Too many requests, try again shortly.
GET/api/plugin/campaign

Returns the funding progress of the campaign tied to the key; call it periodically to refresh the in-game display.

cURL
curl https://keepalive.gg/api/plugin/campaign \
  -H "Authorization: Bearer ka_live_xxxxxxxxxxxxxxxxxxxxxxxx"
Response 200
{
  "campaign": {
    "slug": "skycraft-survie",
    "title": "SkyCraft Survie",
    "game": "minecraft",
    "status": "published",
    "goalKind": "monthly",
    "goalCents": 2000,
    "currency": "EUR",
    "raisedCents": 1450,
    "pct": 73,
    "supporters": 12,
    "rewards": [
      { "minCents": 500, "title": "Role", "description": "…" }
    ]
  }
}

goalCents / raisedCents are in cents · pct already clamped to 0 to 100 · goalKind is monthly or oneshot.

GET/api/plugin/donations

Lists captured donations, oldest first, to grant rewards. The cursor avoids re-fetching old donations.

ParamDefaultDescription
afternoneOpaque cursor: the nextCursor from the previous page. Omit it on the first call.
limit50Max number of donations (capped at 50).
cURL
curl "https://keepalive.gg/api/plugin/donations?after=CURSOR" \
  -H "Authorization: Bearer ka_live_xxxxxxxxxxxxxxxxxxxxxxxx"
Response 200
{
  "donations": [
    {
      "id": "don_9f2c…",
      "donorName": "Nova",
      "amountCents": 1000,
      "currency": "EUR",
      "message": "gg",
      "recurring": false,
      "rewardTitle": "Kit VIP",
      "createdAt": "2026-07-21T18:04:11.000Z"
    }
  ],
  "nextCursor": "2026-07-21T18:04:11.000Z|don_9f2c…"
}

Exposed fields (public only):

FieldDescription
idUnique donation id (used to de-duplicate).
donorNamePublic name entered by the donor (null if anonymous).
amountCentsDonation amount, in cents.
messagePublic message from the donor (null if none).
recurringtrue if it’s a monthly donation.
rewardTitleUnlocked tier to grant in-game (null if none).
createdAtISO 8601 date.

Never an email, a Stripe id or the net amount: only what’s already public on the campaign page.

Recommended polling loop

pseudocode
cursor = load_cursor()               # empty on first run
handled_ids = load_ids()             # anti-duplicate

every 30 to 60 s:
  page = GET /api/plugin/donations?after=cursor
  for each donation in page.donations:
    if donation.id already handled: continue
    if donation.rewardTitle and donation.donorName:
      player = find_player(donation.donorName)
      if player: grant_reward(player, donation.rewardTitle)
    mark donation.id handled
  if page.nextCursor:
    cursor = page.nextCursor ; save(cursor)

Always de-duplicate on id: never grant the same reward twice, even at the cursor boundary.

3. Grant the reward to the right player

KeepAlive doesn’t know the donor’s in-game account, only the public name they entered (donorName). The recommended convention:

Ask your players to donate using their in-game name as the public name.

Your plugin then matches donorName to the player (case-insensitive). If nobody matches at donation time, keep the reward pending and replay it when they reconnect.

Planned: a “claim code” flow (/claim <code> in-game) will make attribution 100% reliable, regardless of the name.

Ready to connect your server?

Generate an API key from your campaign dashboard and follow the examples above.

Open my dashboard