Documentation
This page serves every documentation route. Pick a section from the list; the browser opens the right one.
Getting started
1. Add the bot
Sign in with Discord and choose a server from your dashboard, or use the install link on that server. You are asked to review the permissions before granting them. Panindigan never asks you for a bot token — there is only the one official bot.
2. Grant the permissions it actually needs
Panindigan works with a narrower set than the Discord default invite. For most servers, grant:
- View Channel and Send Messages
- Embed Links, and Attach Files if you use transcripts
- Read Message History for ticket transcripts and summary commands
- Manage Roles only if you use autoroles, reaction roles, or the muted role
- Moderate Members for timeouts
- Ban Members and Kick Members for ban and kick
- Move Members for voice moderation
- Connect and Speak for music
- Manage Channels only if you use lockdown or per-channel slowmode policy
The bot-permissions command reports what Panindigan
currently has and what a given feature still needs, so you can
grant the minimum rather than everything.
3. Find the prefix
The default prefix is p!. You do not have to remember
it: mention the bot directly and it replies with the current
prefix, the command directory, and a link to these docs.
4. Accept the legal documents
Until you accept the current Terms of Service and Privacy Policy, commands are locked. This check happens on the server for every command surface, so a client-side workaround is not possible. Declining keeps commands locked; it is not a deletion request.
Commands
All 421 commands use the prefix interface. 220 of them are also registered as Discord slash commands. Both interfaces resolve to the same canonical command, so behavior never differs between them.
Named arguments, quoted text, and flags
p!ban @someone 7d --reason "repeated advertising"
Durations accept 30s, 10m,
2h, 7d, and 1w. Anything a
command takes has a documented flag; command-info
prints the full contract for any command.
Permissions
Each command declares the Discord permissions it needs from you and from the bot. Both are checked server-side before the command runs, so a command never half-executes.
Cooldowns and rate limits
Every command has a cooldown and a rate limit. Hitting either tells you how long to wait rather than silently failing.
Finding a command
Use the command browser to search all 421 by name, category, interface, or permission level.
Custom commands
A custom command is yours: its name, description, arguments, permissions, cooldown, and its Lua source. Panindigan supplies registration, resolution, authentication, consent, authorization, Discord permission checks, entitlements, sandboxing, execution limits, rate limits, versioning, deployment, rollback, and audit.
Panindigan's own 421 commands are native TypeScript and never run in the Lua runtime. Only your custom commands and automations do.
Lifecycle
- Create
- Define
- Write Lua
- Validate
- Static security check
- API dependency check
- Test
- Preview / diff
- Create version
- Deploy
- Registry
- Sync
- Verify
- Active
A deployed version is immutable. Editing creates a new version, and rollback restores a previously validated one. There is exactly one lifecycle; the dashboard, prefix, slash, automation, and deployment flows all reference the same state model.
A first command
local target = args.user or context.user
local user = api.discord.getUser({
userId = target.id
})
if not user then
return response.error("User not found.")
end
return response.embed({
title = user.displayName .. "'s avatar",
image = user.avatarUrl
})
The editor autocompletes from the live API registry, so anything it offers is an API that actually exists and is active for your plan.
The Lua API
Your Lua calls Panindigan APIs, never Discord.js. You receive safe, serialisable values — not live clients, guilds, members, or channels.
Namespaces
api.discord.*— users, members, messages, channelsapi.guild.*— configuration and server factsapi.channel.*,api.user.*,api.member.*api.database.*,api.cache.*— scoped, never raw SQLapi.http.*— controlled, SSRF-protected, optionalapi.bot.*,api.scheduler.*,api.utility.*,api.plugin.*
What Lua cannot do
It cannot read the bot token, OAuth secrets, database or Redis credentials, storage credentials, payment secrets, or signing keys. It cannot run shell commands, spawn processes, read arbitrary files, load native modules, open arbitrary sockets, execute raw SQL, reach Discord.js internals, or bypass permissions, entitlements, cooldowns, or rate limits.
Response contract
return response.text("Hello!")
return response.success("Command completed.")
return response.error("User not found.")
return response.message({ content = "Hello!", ephemeral = true })
Limits
Every execution is bounded by CPU time, memory, instruction count, API-call count and timeout, output size, recursion depth, concurrency, and per-user, per-guild, and global quotas. The effective limit is set server-side and can only be more restrictive than the baseline, never less.
Every call is authorized independently
Panindigan revalidates your permissions, the bot's permissions, guild policy, channel policy, role restrictions, the API's own permissions, entitlements, and rate limits before each API call runs. Your Lua is never the authority.
Automation
An automation is a trigger, a set of conditions, and an action. Triggers cover member join and leave, messages, reactions, schedules, role changes, ticket events, and moderation events.
Schedules are timezone-aware: the expression is interpreted in the server's configured timezone, not the operator's, so a daily job fires at the same wall-clock time regardless of who set it up and across daylight-saving changes.
Use automation-test to run a workflow in a safe test
context before enabling it. History and error diagnostics are
available from the dashboard.
An automation may invoke a production command through the same command engine a user would. That does not move command logic into Lua; user Lua runs only inside the sandbox.
The dashboard
Sign in with Discord and pick a server. The dashboard navigation mirrors the 15 command categories, so nothing in the UI implies a feature the catalog does not have.
Administration versus configuration
Administration is high-privilege server management: prefix and command policy, role and channel mapping, staff access, module control, allow and ignore rules, audit access, dangerous actions, and reset and recovery. Configuration is preference and default setting: language, timezone, logging destinations, notification defaults, and per-feature settings. They are separate because they carry different authorization.
Welcome and Goodbye
They live under Community & Member Notifications → Notifications, not as a separate category. They are real member-lifecycle delivery pipelines: a delivery is reported as successful only after Discord confirms the message was sent, and every attempt appears in delivery history with its state.
Your account
Discord OAuth is the only customer identity provider, so there is no password to change. Account security shows your Discord account, this device, your active sessions, a real recent-activity timeline, dynamic recommendations, and a Danger Zone with disconnect and delete.
The API
The canonical API base is https://api.bot.panindigan.com/api/v1.
Every stable resource lives under that version. The OpenAPI
contract is owned by the backend repository; nothing in the API
silently changes meaning without a version bump.
Resources that are public
GET /api/v1/status,/status/services,/status/incidents,/status/uptimeGET /api/v1/commands,/commands/:commandSlugGET /api/v1/pricing,/changelog,/docs/search
Resources that require a session
Guild resources require a Discord session, server context in every
mutating request, server-side guild membership checks, and CSRF
protection for cookie-authenticated browser calls. A client
supplied guildId is never trusted on its own.
Response envelope
{
"success": true,
"data": {},
"meta": { "requestId": "req_...", "apiVersion": "v1" }
}
Errors use the same shape with a stable error code. Internal queue identifiers, worker hostnames, credentials, database identifiers, Redis keys, and stack traces never cross the public boundary.
During maintenance
Protected operations return 503 with
MAINTENANCE_ACTIVE and the opaque maintenance ID,
after authentication and before the protected mutation runs.
Developer tools
registryandregistry-search— registry status and lookup.sync,sync-status,drift— slash synchronisation health and drift detection.deployment,deployment-validate,deployment-preview— what a release would change, before it does.executionandruntime— inspect an execution ID and worker health.api-list,api-info,api-test— the callable API contract and safe tests.custom-validate,custom-deploy,custom-rollback,custom-history— custom command lifecycle.