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.

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

command
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

  1. Create
  2. Define
  3. Write Lua
  4. Validate
  5. Static security check
  6. API dependency check
  7. Test
  8. Preview / diff
  9. Create version
  10. Deploy
  11. Registry
  12. Sync
  13. Verify
  14. 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

lua
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, channels
  • api.guild.* — configuration and server facts
  • api.channel.*, api.user.*, api.member.*
  • api.database.*, api.cache.* — scoped, never raw SQL
  • api.http.* — controlled, SSRF-protected, optional
  • api.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

lua
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/uptime
  • GET /api/v1/commands, /commands/:commandSlug
  • GET /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

json
{
  "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

  • registry and registry-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.
  • execution and runtime — 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.
Reconnecting to live updates…