Skip to content
TipPage Docs
Esc
navigateopen⌘Jpreview
On this page

Guides

Putting the API to work - the chat bot loop, viewer sub-reward credits, AI voices, and a worked end-to-end example.

The chat bot: speak and manage commands

The chat.command webhook is one half of a loop - the other half is making the bot talk back. Together they turn the bot into a thin client for your own service:

  • GET /v1/bot - whether the bot is on, which channel it’s in, and the identity it speaks as (the shared TipPageBot or the streamer’s linked custom bot). Any valid key.
  • POST /v1/chat/messages - the bot says your message in chat, verbatim (chat:write) - in every connected chat, or just Twitch or Kick with platform. Messages can’t start with / or !, and sends have their own rate budget (20 per 30 seconds per streamer).
  • /v1/commands - full CRUD over the bot’s custom !commands (commands:manage), addressed by command name. The same rows as the dashboard’s Chat bot page: responses, permission levels, cooldowns, aliases, platforms (which chats it answers in) and per-command enable switches, with the same template variables ({user}, {args}, {pick:...}, {if:...}, {ai:...}, …). Changes reach chat within a few seconds. chat.command tells you which platform the viewer typed in, so a reply can go back to that chat alone.

So a game-integration can create !loadout at stream start, update its response as the loadout changes, and delete it at stream end - or skip stored responses entirely: catch chat.command on your server, compute the answer, and POST it back through /v1/chat/messages. Built-in commands, built-in aliases, and response lists stay dashboard surfaces (command responses can still use {list:name} lists managed there).

Viewers and sub-reward credits

Streamers with sub rewards enabled give subscribers free TTS/media credits; viewers sign in to the tip page (with Twitch or Kick) to see and spend them. The viewers:read and viewers:manage scopes put that whole system under automation - award bonus credits from your own loyalty bot, sync balances into Discord, or audit who’s actually using their rewards.

  • GET /v1/viewers - everyone who has signed in, most recent first, with first-sign-in dates and credit balances. Every viewer object says which account they signed in with (platform + platform_user_id) and lists their linked_accounts on the other platform.
  • GET /v1/viewers/{user} - one viewer in full: profile, sign-in date, balance (including gift-sub credits still pending sign-in), the grant-by-grant ledger, and usage totals.
  • GET /v1/viewers/{user}/rewards - their played sub-reward messages, paginated like /tts/history.
  • POST /v1/viewers/{user}/credits/grant / revoke - move credits, same as the dashboard’s Viewers page. Revoking only ever touches unused credits.

{user} takes <platform>:<id> (twitch:123456789, kick:123), a bare numeric id, or the viewer’s name (login or display name, case-insensitive, on either platform) - so all of these grant GigaChad42 three credits:

curl -X POST https://api.tippage.com/v1/viewers/twitch:123456789/credits/grant \
  -H "Authorization: Bearer tp_live_..." \
  -H "Content-Type: application/json" -d '{"amount": 3}'

curl -X POST https://api.tippage.com/v1/viewers/123456789/credits/grant \
  -H "Authorization: Bearer tp_live_..." \
  -H "Content-Type: application/json" -d '{"amount": 3}'

curl -X POST https://api.tippage.com/v1/viewers/GigaChad42/credits/grant \
  -H "Authorization: Bearer tp_live_..." \
  -H "Content-Type: application/json" -d '{"amount": 3}'

Prefer platform:id in automation - it survives renames and can never be ambiguous. A bare id is tried on Twitch then Kick and answers 409 ambiguous_viewer if an account with that id signed in on both; a name shared by two different people is 409 too (a name that matches both of one person’s linked accounts just resolves to the one they signed in with most recently). A grant or revoke lands on the account you named; balances and history are read across the person’s linked accounts either way.

One rule to design around: a viewer exists only once they’ve signed in to the tip page. Granting (or looking up) anyone who never has answers 404 with code viewer_not_signed_in and grants nothing - there’s no account to attach the credits to yet. Have the viewer sign in first, then grant. (Gift-sub credits from Twitch events are the one exception: those wait in a pending pool and attach automatically on first sign-in - you’ll see them as credits.pending on the viewer detail.)

AI voices

Accounts in the AI voices closed beta can let viewers have their tip read out in AI voices - one voice for the whole message, or a script where different lines are spoken by different voices (up to five in one message, performed as a single take). Voices are TipPage’s own, cloned by the streamer from their own recordings, or published by another streamer. The ai_voices:manage scope exposes the feature to automation:

  • GET /v1/ai-voices - the feature’s state (on/off, mode, minimum tip), every voice the account can offer with per-voice enabled flags, a source (platform/own/shared) and sample clips, plus this month’s generation figures. Those figures are informational - there is no monthly allowance.
  • POST /v1/ai-voices/enable / disable - the master switch, same as the dashboard toggle. Handy for turning AI voices on only while live.
  • POST /v1/ai-voices/{voiceId}/enable / disable - curate which voices viewers can pick, by the ids from the catalog. The last enabled voice can’t be disabled - use the master switch instead.

Cloning and publishing voices is dashboard-only; there is deliberately no /v1 surface for uploading someone’s voice.

Every /v1/ai-voices endpoint answers 404 for accounts without the feature - the scope won’t appear in your dashboard’s key editor either.

A worked example: react to tips from your own server

  1. Create a key with tts:read + tts:control.
  2. Add a webhook endpoint subscribed to tip.created - or skip webhooks and poll GET /v1/tts/queue every few seconds.
  3. When a tip arrives, claim it with POST /v1/tts/{orderId}/start - the same call the overlay makes, so the dashboard shows it as playing and nothing else can double-play it.
  4. Do your thing - light the lights, post to Discord, play the audio from tts_url on your own device.
  5. Finish with POST /v1/tts/{orderId}/finish to promote it to history and free the queue for the next tip.

If your integration should be the alert experience, turn off the overlay’s TTS so the queue has one consumer. The full protocol - the gates, crash recovery, and the do’s and don’ts - is in Claim, do your thing, finish.

Was this page helpful?