Kick API Guide: OAuth 2.1, Endpoints, Scopes, and Rate Limits
When building applications for Kick, understanding the Kick API is essential for automating your streaming workflow. In this guide, I will help you set up and understand the API structure, authentication flows, and available endpoints. Kick offers a comprehensive API for developers to interact with channels, chat, moderation, livestreams, and more. This guide focuses on the official Kick Developer API and its OAuth 2.1 authentication system.
This tutorial provides a simplified overview of the Kick API. If you are looking for automated content reposting across platforms, check out Repostit.io for a streamlined automation solution.
Kick API OAuth 2.1 Authentication
The Kick API uses OAuth 2.1 for authentication, providing a secure and modern authorization framework. The Kick API OAuth server is hosted at https://id.kick.com, which is separate from the main Kick API server at https://api.kick.com. Understanding the difference between these servers is crucial for implementing Kick API authentication correctly.
Token Types
The Kick API provides two types of access tokens, each designed for different use cases:
| Token Type | OAuth Flow | Use Case | Access Level |
|---|---|---|---|
| App Access Token | Client Credentials | Server-to-server API calls without user login | Public data only |
| User Access Token | Authorization Code Grant | Access user data and act on behalf of users | Based on granted scopes |
App Access Tokens are generated through the Client Credentials flow. These server-to-server tokens are the most basic form of API access, allowing you to retrieve publicly available data without requiring user login. They are ideal for displaying public stream information or category listings.
User Access Tokens are generated through the Authorization Code Grant flow with PKCE. These tokens provide access to user-specific information based on the scopes your application has requested. With appropriate scopes, your application can act on the user’s behalf, such as sending chat messages or managing channel settings.
Kick API Authorization Code Flow with PKCE
For User Access Tokens, the Kick API implements the Authorization Code flow with PKCE (Proof Key for Code Exchange), which provides enhanced security for public clients. Here is the step-by-step process for Kick API authentication:
- Register your app: Create an application on the Kick Developer Portal and copy your client_id and client_secret.
- Generate PKCE codes: Create a
code_verifier(random string) and derive thecode_challengeusing SHA-256 hashing. - Set up a callback receiver: Run a local HTTP server (e.g.,
http://localhost:5000/callback) to catch the redirect and read thecodequery parameter. - Direct user to authorize: Open the Kick authorization URL in the browser with your parameters.
GET https://id.kick.com/oauth/authorize?
response_type=code&
client_id=YOUR_CLIENT_ID&
redirect_uri=https://yourapp.com/callback&
scope=user:read channel:read chat:write&
code_challenge=YOUR_CODE_CHALLENGE&
code_challenge_method=S256&
state=RANDOM_STATE_VALUE
- User approves access: The user logs in to Kick and approves your application’s requested scopes.
- Capture the authorization code: After consent, Kick redirects to your URI with
?code=AUTH_CODE&state=.... - Exchange code for tokens: Send the authorization code along with your credentials to the token endpoint.
- Store and use tokens: Securely store the access and refresh tokens. Use
Authorization: Bearer <access_token>in API requests.
Token Exchange Example
After receiving the authorization code, exchange it for access and refresh tokens:
POST https://id.kick.com/oauth/token Headers: Content-Type: application/x-www-form-urlencoded Body: grant_type=authorization_code client_id=YOUR_CLIENT_ID client_secret=YOUR_CLIENT_SECRET redirect_uri=https://yourapp.com/callback code_verifier=YOUR_CODE_VERIFIER code=AUTHORIZATION_CODE
The response will contain your tokens:
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"refresh_token": "def50200abc123...",
"expires_in": 3600,
"scope": "user:read channel:read chat:write"
}
Kick API App Access Token (Client Credentials)
For server-to-server requests that only need public data, use the Client Credentials flow to obtain an App Access Token:
POST https://id.kick.com/oauth/token Headers: Content-Type: application/x-www-form-urlencoded Body: grant_type=client_credentials client_id=YOUR_CLIENT_ID client_secret=YOUR_CLIENT_SECRET
Response:
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_in": 3600,
"token_type": "Bearer"
}
Kick API Available Scopes
Scopes define the level of access your application requests from users. Each scope grants permission to specific endpoints and actions. The following table lists all available scopes:
| Scope | Description |
|---|---|
user:read |
View user information including username, streamer ID, profile picture |
channel:read |
View channel information including description, category, stream status |
channel:write |
Update livestream metadata for a channel (title, category, tags) |
channel:rewards:read |
Read channel points rewards information |
channel:rewards:write |
Create, edit, and delete channel points rewards |
chat:write |
Send chat messages and allow chat bots to post in chat |
streamkey:read |
Read a user’s stream URL and stream key |
events:subscribe |
Subscribe to channel events (chat messages, follows, subscriptions) |
moderation:ban |
Execute ban and unban actions on users |
moderation:chat_message:manage |
Delete and manage chat messages |
kicks:read |
View KICKs related information (leaderboards, gifted amounts) |
Kick API Endpoints Overview
The Kick API is hosted at https://api.kick.com and provides endpoints for various platform features. All Kick API requests require authentication via Bearer token. Below is an overview of the main Kick API categories:
Users Endpoint
The Users endpoint retrieves user information based on provided user IDs. If no IDs are specified, it returns information for the currently authenticated user.
| Endpoint | Method | Required Scope | Description |
|---|---|---|---|
/public/v1/users |
GET | user:read |
Get user information by ID or current user |
Example request:
GET https://api.kick.com/public/v1/users?id=123&id=456 Headers: Authorization: Bearer YOUR_ACCESS_TOKEN
Example response:
{
"data": [
{
"user_id": 123,
"name": "John Doe",
"email": "john.doe@example.com",
"profile_picture": "https://kick.com/img/default-profile-pictures/default-avatar-2.webp"
}
],
"message": "OK"
}
Channels Endpoint
The Channels endpoint lets you retrieve and update channel information. You can query by broadcaster user ID or channel slug.
| Endpoint | Method | Required Scope | Description |
|---|---|---|---|
/public/v1/channels |
GET | channel:read |
Get channel information by broadcaster ID or slug |
/public/v1/channels |
PATCH | channel:write |
Update livestream metadata (title, category, tags) |
Example GET request:
GET https://api.kick.com/public/v1/channels?slug=john-doe Headers: Authorization: Bearer YOUR_ACCESS_TOKEN
Example response:
{
"data": [
{
"broadcaster_user_id": 123,
"slug": "john-doe",
"stream_title": "My first stream",
"channel_description": "Welcome to my channel!",
"category": {
"id": 101,
"name": "Just Chatting",
"thumbnail": "https://kick.com/img/categories/just-chatting.jpeg"
},
"stream": {
"is_live": true,
"viewer_count": 150,
"start_time": "2026-01-31T10:00:00Z",
"language": "en"
}
}
],
"message": "OK"
}
Example PATCH request to update stream metadata:
PATCH https://api.kick.com/public/v1/channels
Headers:
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
Body:
{
"stream_title": "Playing Rust with friends!",
"category_id": 101,
"custom_tags": ["survival", "multiplayer"]
}
Categories Endpoint
The Categories endpoint retrieves category information for streams. Categories can be filtered by name, tags, or IDs.
| Endpoint | Method | Description |
|---|---|---|
/public/v2/categories |
GET | Get categories with pagination (recommended) |
/public/v1/categories |
GET | Search categories (deprecated) |
/public/v1/categories/{id} |
GET | Get specific category by ID |
Example request:
GET https://api.kick.com/public/v2/categories?name=Rust&limit=10 Headers: Authorization: Bearer YOUR_ACCESS_TOKEN
Example response:
{
"data": [
{
"id": 101,
"name": "Rust",
"tags": ["FPS", "Shooter", "Adventure"],
"thumbnail": "https://kick.com/img/categories/rust.jpeg"
}
],
"message": "OK",
"pagination": {
"next_cursor": "eyJsYXN0X2lkIjoxMDF9"
}
}
Chat Endpoint
The Chat endpoint allows you to send and manage chat messages in channels. Messages can be sent as a user or as a bot account.
| Endpoint | Method | Required Scope | Description |
|---|---|---|---|
/public/v1/chat |
POST | chat:write |
Send a chat message to a channel |
/public/v1/chat/{message_id} |
DELETE | moderation:chat_message:manage |
Delete a chat message |
Example POST request to send a chat message:
POST https://api.kick.com/public/v1/chat
Headers:
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
Body:
{
"broadcaster_user_id": 123,
"content": "Hello everyone!",
"type": "user"
}
Example response:
{
"data": {
"is_sent": true,
"message_id": "828f83bb-e391-4c78-9e91-af35a172840e"
},
"message": "OK"
}
To reply to a specific message, include the reply_to_message_id field:
{
"broadcaster_user_id": 123,
"content": "Thanks for the follow!",
"type": "user",
"reply_to_message_id": "828f83bb-e391-4c78-9e91-af35a172840e"
}
Livestreams Endpoint
The Livestreams endpoint retrieves information about live streams across the platform.
| Endpoint | Method | Description |
|---|---|---|
/public/v1/livestreams |
GET | Get livestreams filtered by broadcaster, category, language |
/public/v1/livestreams/stats |
GET | Get total count of active livestreams |
Example request with filters:
GET https://api.kick.com/public/v1/livestreams?category_id=101&language=en&sort=viewer_count&limit=20 Headers: Authorization: Bearer YOUR_ACCESS_TOKEN
Example response:
{
"data": [
{
"broadcaster_user_id": 123,
"slug": "john-doe",
"stream_title": "Late night gaming",
"viewer_count": 1500,
"started_at": "2026-01-31T22:00:00Z",
"language": "en",
"has_mature_content": false,
"category": {
"id": 101,
"name": "Rust"
},
"custom_tags": ["chill", "gaming"]
}
],
"message": "OK"
}
Moderation Endpoint
The Moderation endpoint allows you to manage user participation in chat through bans and timeouts.
| Endpoint | Method | Required Scope | Description |
|---|---|---|---|
/public/v1/moderation/bans |
POST | moderation:ban |
Ban or timeout a user from chat |
/public/v1/moderation/bans |
DELETE | moderation:ban |
Unban or remove timeout from a user |
Example ban request (permanent ban if no duration specified):
POST https://api.kick.com/public/v1/moderation/bans
Headers:
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
Body:
{
"broadcaster_user_id": 123,
"user_id": 456,
"reason": "Spam"
}
Example timeout request (10 minute timeout):
{
"broadcaster_user_id": 123,
"user_id": 456,
"duration": 10,
"reason": "Cool down"
}
The duration field accepts values from 1 to 10080 minutes (7 days maximum).
Channel Rewards Endpoint
The Channel Rewards endpoint lets you manage channel points rewards for your channel. Channels can have up to 15 rewards configured.
| Endpoint | Method | Required Scope | Description |
|---|---|---|---|
/public/v1/channels/rewards |
GET | channel:rewards:write |
Get all channel rewards |
/public/v1/channels/rewards |
POST | channel:rewards:write |
Create a new reward |
/public/v1/channels/rewards/{id} |
PATCH | channel:rewards:write |
Update a reward |
/public/v1/channels/rewards/{id} |
DELETE | channel:rewards:write |
Delete a reward |
/public/v1/channels/rewards/redemptions |
GET | channel:rewards:write |
Get reward redemptions |
/public/v1/channels/rewards/redemptions/accept |
POST | channel:rewards:write |
Accept redemptions |
/public/v1/channels/rewards/redemptions/reject |
POST | channel:rewards:write |
Reject redemptions |
Example create reward request:
POST https://api.kick.com/public/v1/channels/rewards
Headers:
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
Body:
{
"title": "Song Request",
"cost": 100,
"description": "Request a song by providing a URL",
"background_color": "#00e701",
"is_enabled": true,
"is_user_input_required": true,
"should_redemptions_skip_request_queue": false
}
KICKs Leaderboard Endpoint
The KICKs Leaderboard endpoint retrieves leaderboard data for KICKs (the platform’s gifting currency).
| Endpoint | Method | Required Scope | Description |
|---|---|---|---|
/public/v1/kicks/leaderboard |
GET | kicks:read |
Get KICKs leaderboard (weekly, monthly, lifetime) |
Example request:
GET https://api.kick.com/public/v1/kicks/leaderboard?top=10 Headers: Authorization: Bearer YOUR_ACCESS_TOKEN
Example response:
{
"data": {
"week": [
{"rank": 1, "user_id": 123, "username": "generous_viewer", "gifted_amount": 500}
],
"month": [
{"rank": 1, "user_id": 123, "username": "generous_viewer", "gifted_amount": 2000}
],
"lifetime": [
{"rank": 1, "user_id": 123, "username": "generous_viewer", "gifted_amount": 15000}
]
},
"message": "OK"
}
Kick API Token Management
Refreshing Tokens
Access tokens expire after a set period. Use the refresh token to obtain new tokens without requiring user re-authorization:
POST https://id.kick.com/oauth/token Headers: Content-Type: application/x-www-form-urlencoded Body: grant_type=refresh_token client_id=YOUR_CLIENT_ID client_secret=YOUR_CLIENT_SECRET refresh_token=YOUR_REFRESH_TOKEN
Revoking Tokens
When a user logs out or you need to invalidate tokens:
POST https://id.kick.com/oauth/revoke?token=YOUR_TOKEN&token_hint_type=access_token Headers: Content-Type: application/x-www-form-urlencoded
Token Introspection
Check if a token is valid and get information about it:
POST https://id.kick.com/oauth/token/introspect Headers: Authorization: Bearer YOUR_ACCESS_TOKEN
Response:
{
"data": {
"active": true,
"client_id": "0144Y845NBDSST5H2G1DVY2T25",
"token_type": "user",
"scope": "user:read channel:read",
"exp": 1771046347
},
"message": "OK"
}
Kick API Python Implementation Example
Here is a complete Python example demonstrating how to authenticate and make API requests:
import requests
import hashlib
import base64
import secrets
import json
# === CONFIG ===
CLIENT_ID = "YOUR_CLIENT_ID"
CLIENT_SECRET = "YOUR_CLIENT_SECRET"
REDIRECT_URI = "http://localhost:5000/callback"
# === Generate PKCE codes ===
code_verifier = secrets.token_urlsafe(64)
code_challenge = base64.urlsafe_b64encode(
hashlib.sha256(code_verifier.encode()).digest()
).decode().rstrip("=")
# === Step 1: Build authorization URL ===
auth_url = (
f"https://id.kick.com/oauth/authorize?"
f"response_type=code&"
f"client_id={CLIENT_ID}&"
f"redirect_uri={REDIRECT_URI}&"
f"scope=user:read channel:read chat:write&"
f"code_challenge={code_challenge}&"
f"code_challenge_method=S256&"
f"state={secrets.token_urlsafe(16)}"
)
print("Open this URL to authorize:", auth_url)
# === Step 2: After user authorizes, exchange code for tokens ===
auth_code = input("Enter the authorization code: ")
token_response = requests.post(
"https://id.kick.com/oauth/token",
headers={"Content-Type": "application/x-www-form-urlencoded"},
data={
"grant_type": "authorization_code",
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET,
"redirect_uri": REDIRECT_URI,
"code_verifier": code_verifier,
"code": auth_code
}
)
tokens = token_response.json()
access_token = tokens["access_token"]
print("Access Token obtained!")
# === Step 3: Make API request ===
user_response = requests.get(
"https://api.kick.com/public/v1/users",
headers={"Authorization": f"Bearer {access_token}"}
)
print("User Info:", json.dumps(user_response.json(), indent=2))
Kick API Error Handling
The Kick API returns standard HTTP status codes to indicate success or failure of Kick API requests:
| Status Code | Meaning | Common Cause |
|---|---|---|
| 200 | OK | Request successful |
| 204 | No Content | Request successful, no response body |
| 400 | Bad Request | Invalid parameters or malformed request |
| 401 | Unauthorized | Invalid or expired token |
| 403 | Forbidden | Token lacks required scope |
| 404 | Not Found | Resource does not exist |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server-side issue |
Kick API Workaround for localhost Development
If you are developing locally with 127.0.0.1 as your redirect URI for Kick API authentication, you may encounter issues due to a bug in Kick’s frontend framework (NextJS). NextJS automatically converts the first occurrence of 127.0.0.1 to localhost, which can cause Kick API authorization to fail because the redirect URI must match exactly.
The recommended solution is to use localhost instead of 127.0.0.1. However, if you cannot change your callback URL, add a sacrificial query parameter containing 127.0.0.1 before the redirect_uri parameter:
GET https://id.kick.com/oauth/authorize?
response_type=code&
client_id=YOUR_CLIENT_ID&
redirect=127.0.0.1&
redirect_uri=http://127.0.0.1/callback&
scope=user:read&
code_challenge=YOUR_CODE_CHALLENGE&
code_challenge_method=S256&
state=RANDOM_VALUE
The redirect=127.0.0.1 parameter will be converted to localhost, leaving the actual redirect_uri parameter unchanged.
Kick API Best Practices
- Store secrets securely: Never expose your
client_secretin client-side code. Keep all sensitive Kick API credentials server-side. - Request minimal scopes: Only request the Kick API scopes your application actually needs. Users are more likely to approve apps with focused permissions.
- Handle token expiration: Implement automatic Kick API token refresh before expiration to maintain seamless user experience.
- Implement rate limiting: Respect Kick API rate limits and implement exponential backoff for retries.
- Use HTTPS: All production redirect URIs for Kick API should use HTTPS for security.
- Validate state parameter: Always validate the
stateparameter in the Kick API callback to prevent CSRF attacks.