Create a command
name is the trigger without the ! prefix; the bot’s built-in triggers are reserved. Responses support the same template variables as the dashboard’s Chat bot page - {user}, {touser}, {args}, {arg:N}, {pick:a|b|c}, {random:1-100}, {list:name}, {if:...}, {repeat:N|...}, {uptime}, {ai:...} and more, and variables nest (full reference: https://docs.tippage.com/chat-bot/variables). Response lists themselves are managed in the dashboard. Requires commands:manage.
POST
/commandsAuthorization
AuthorizationBearer token (tp_live_... or tpat_...) · headerrequiredA TipPage API key (`tp_live_...`, created in Dashboard → Settings → Developer) or an OAuth 2.0 access token (`tpat_...`, see the OAuth guide). Both carry the same scopes and are accepted on every endpoint.
Request body
requiredapplication/jsonnamestringrequiredThe trigger without the `!` prefix - lowercase letters, numbers, hyphens, and underscores. The bot's built-in triggers are reserved.
max length 50 · matches ^[a-z0-9_-]+$
responsestringrequiredThe template. Can't start with `/` or `!`; the rendered chat line is cut to 500.
max length 2500
descriptionstring | nullViewer-facing blurb for the tip page's command list. Plain text.
max length 200
listedbooleandefault: true
ai_memorybooleandefault: false
ai_memory_sharedbooleandefault: false
platformsstring[]Which chat(s) the command answers in. At least one.
default: ["twitch","kick"]
permissionstringdefault: "everyone"
Allowed:
everyonesubscribermoderatorcooldown_secondsintegermin 0 · max 3600 · default: 0
cooldown_typestringdefault: "global"
Allowed:
globalper_useraliasesstring[]Same lexical rules as `name`; max 10.
max items 10
enabledbooleandefault: true
Responses
201Created. Active in chat within a few seconds.
commandCustomCommandShow propertiesHide properties
namestringThe trigger, without the `!` prefix.
responsestringWhat the bot answers. Template variables supported.
descriptionstring | nullOptional viewer-facing blurb shown on the tip page's command list instead of the response. `null` = the page shows a preview of the response with variables rendered as labels (`{urlfetch:}` addresses and `{ai:}` prompts are never shown).
max length 200
listedbooleanWhether the command appears on the tip page's command list. It works in chat either way.
ai_memoryboolean`{ai:}` conversation memory - when true the character remembers this command's last 15 exchanges (with timestamps, kept until the command is deleted) and reacts to repeats and returning viewers. Only meaningful for responses containing `{ai:}`. Memory is per platform unless `ai_memory_shared`.
ai_memory_sharedbooleanOne memory for Twitch and Kick instead of one per platform. Only meaningful with `ai_memory`.
platformsstring[]Which chat(s) it runs in. Default both. A platform the streamer hasn't connected is simply skipped; the set can't be empty (use `enabled: false` to bench it).
permissionstringWho can trigger it. `subscriber` includes moderators; `moderator` includes the streamer.
Allowed:
everyonesubscribermoderatorcooldown_secondsintegermin 0 · max 3600
cooldown_typestring`global` = one shared cooldown for the whole channel; `per_user` = each viewer gets their own.
Allowed:
globalper_useraliasesstring[]Extra triggers for the same command, also without the `!`.
enabledbooleancreated_atstring<date-time>updated_atstring<date-time>400Invalid fields (`invalid_command`).
errorstringrequiredHuman-readable message.
codestringMachine-readable code (e.g. `missing_scope`, `not_in_queue`).
401Missing or invalid credential (`missing_api_key` / `invalid_api_key`, or `invalid_token` for an expired/revoked OAuth access token).
errorstringrequiredHuman-readable message.
codestringMachine-readable code (e.g. `missing_scope`, `not_in_queue`).
403The key lacks the required scope (`missing_scope`).
errorstringrequiredHuman-readable message.
codestringMachine-readable code (e.g. `missing_scope`, `not_in_queue`).
required_scopestring409Name already taken (`command_exists`), or an alias collides with another trigger (`alias_in_use`).
errorstringrequiredHuman-readable message.
codestringMachine-readable code (e.g. `missing_scope`, `not_in_queue`).
429Rate limit exceeded - check the `RateLimit-*` headers.
errorstringRequest
curl -X POST "https://api.tippage.com/v1/commands" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "string",
"response": "string",
"description": "string",
"listed": true,
"ai_memory": false,
"ai_memory_shared": false,
"platforms": [
"twitch",
"kick"
],
"permission": "everyone",
"cooldown_seconds": 0,
"cooldown_type": "global",
"aliases": [
"string"
],
"enabled": true
}'const response = await fetch("https://api.tippage.com/v1/commands", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_TOKEN",
"Content-Type": "application/json"
},
body: JSON.stringify({
"name": "string",
"response": "string",
"description": "string",
"listed": true,
"ai_memory": false,
"ai_memory_shared": false,
"platforms": [
"twitch",
"kick"
],
"permission": "everyone",
"cooldown_seconds": 0,
"cooldown_type": "global",
"aliases": [
"string"
],
"enabled": true
})
});import requests
response = requests.post(
"https://api.tippage.com/v1/commands",
headers={
"Authorization": "Bearer YOUR_TOKEN",
"Content-Type": "application/json"
},
json={
"name": "string",
"response": "string",
"description": "string",
"listed": True,
"ai_memory": False,
"ai_memory_shared": False,
"platforms": [
"twitch",
"kick"
],
"permission": "everyone",
"cooldown_seconds": 0,
"cooldown_type": "global",
"aliases": [
"string"
],
"enabled": True
},
)Response
{
"command": {
"name": "discord",
"response": "string",
"description": "string",
"listed": true,
"ai_memory": true,
"ai_memory_shared": true,
"platforms": [
"twitch"
],
"permission": "everyone",
"cooldown_seconds": 3600,
"cooldown_type": "global",
"aliases": [
"string"
],
"enabled": true,
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z"
}
}{
"error": "string",
"code": "string"
}{
"error": "string",
"code": "string"
}{
"error": "string",
"code": "string",
"required_scope": "string"
}{
"error": "string",
"code": "string"
}{
"error": "string"
}