Endpoint reference
Base URL: https://phantombot.gg/api/v1
Every endpoint requires Authorization: Bearer phk_live_…. The scope column tells you which permission the token needs — see Authentication.
Collection endpoints accept ?page=1&per_page=25. per_page is capped at 100; the default is 25. Responses include has_more so you can drive pagination without parsing Link headers.
Meta
| Method | Path | Scope | What it does |
|---|---|---|---|
GET | /me | — | The token's metadata (id, name, scopes, last-used). |
GET | /health | — | Liveness probe. Returns { "status": "ok" }. |
GET /me
curl https://phantombot.gg/api/v1/me \
-H "Authorization: Bearer phk_live_…"{
"token": {
"id": "42",
"name": "Production deploy script",
"preview": "phk_live_AbCdEfGh…0123",
"guild_id": "123456789012345678",
"scopes": ["cases:read", "cases:write"],
"expires_at": null,
"created_at": "2026-05-24T10:30:00+00:00",
"last_used_at": "2026-05-24T11:15:42+00:00"
},
"api": { "version": "v1", "env": "live" }
}Guild
| Method | Path | Scope | |
|---|---|---|---|
GET | /guild | guild:read | Headline metadata. |
GET | /guild/settings | guild:read | Module toggles + a few public knobs. |
Cases
| Method | Path | Scope | |
|---|---|---|---|
GET | /cases | cases:read | List cases. Filters: user_id, type, status, since. |
GET | /cases/{id} | cases:read | A single case. |
POST | /cases | cases:write | Create a note or warn case. |
Create a case
curl -X POST https://phantombot.gg/api/v1/cases \
-H "Authorization: Bearer phk_live_…" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"user_id": "234567890123456789",
"moderator_id": "345678901234567890",
"type": "warn",
"reason": "Posting referral spam"
}'type is restricted to note or warn via this endpoint — punishments that change Discord state (kick, ban, timeout, mute) are not exposed yet. Use the dashboard or wait for the next release.
Emits case.created to subscribed webhooks.
Economy
| Method | Path | Scope | |
|---|---|---|---|
GET | /economy/wallet/{userId} | economy:read | Wallet for one member. Returns a zero-balance shell if they haven't earned anything yet. |
GET | /economy/leaderboard | economy:read | Top wallets, descending. |
POST | /economy/adjust | economy:write | Atomic balance change with a ledger row. |
Adjust balance
curl -X POST https://phantombot.gg/api/v1/economy/adjust \
-H "Authorization: Bearer phk_live_…" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{ "user_id": "234567890123456789", "delta": 500, "reason": "Tournament prize" }'deltais integer, can be negative.- Negative deltas that would push the balance below zero return
422 balance_would_be_negative. - Every adjustment writes a row to the economy ledger with
note: "api:token=<your token id>"so audits can trace back to source.
Emits economy.balance_changed.
Levelling
| Method | Path | Scope | |
|---|---|---|---|
GET | /levelling/user/{userId} | levelling:read | One member's XP + level + progress to next level. |
GET | /levelling/leaderboard | levelling:read | Top members by XP. |
The user endpoint returns a sensible zero-shell for members who haven't sent a message yet (level 0, full bar empty).
Tickets
| Method | Path | Scope | |
|---|---|---|---|
GET | /tickets | tickets:read | List tickets. Filters: status, opener_id, claimed_by_id. |
GET | /tickets/{id} | tickets:read | A single ticket. |
Write endpoints (reply, claim, close) are landing in the next release.
Giveaways
| Method | Path | Scope | |
|---|---|---|---|
GET | /giveaways | giveaways:read | List giveaways. Filter: status. |
GET | /giveaways/{id} | giveaways:read | A single giveaway. |
Write endpoints (end / reroll) are landing in the next release.
Phantom Network
| Method | Path | Scope | |
|---|---|---|---|
GET | /network/lookup/{userId} | network:read | Cross-guild ban-intel lookup. |
Returns { "data": { "listed": false } } for clean users and the full public hit summary (trust score, report count, category, severity, first/last report) for listed ones.
Response envelopes
Collections always look like this:
{
"data": [ /* … */ ],
"page": 1,
"per_page": 25,
"has_more": true
}Singletons look like this:
{ "data": { /* … */ } }Errors:
{ "error": { "code": "…", "message": "…" } }