Python SDK for publishing media on Slike platform
Project description
slike
Python and TypeScript/JavaScript SDK for the Slike platform.
Supports chunked file upload (4 MiB chunks), editor-video registration, publish-by-URL (Google Drive, YouTube, direct links), media status checks, metadata retrieval, agency listing, media update, upload cancellation (local + server-side), CMS user creation, and team-by-host lookup. Two auth flows: direct Slike token or Denmark JWT.
- Python requires 3.7+
- TypeScript/JS requires Node 18+ (or modern browser with Fetch API)
Install
Python
pip3 install slike
JavaScript / TypeScript
npm install slike
Python SDK
Quick start
from slike import SlikeMedia
client = SlikeMedia(token="your-slike-token", environment="prod")
client.initialize() # validates token; raises SlikeAPIError on failure
# Upload a local file (blocking)
result = client.register_media(
file_path="/path/to/video.mp4",
title="My Video",
description="Description",
on_progress=lambda done, total: print(f"{done}/{total} chunks"),
)
print("Media ID:", result["id"])
Denmark JWT auth
client = SlikeMedia(
denmark_token="<jwt>",
service="slike", # optional, default: "slike"
environment="prod",
)
client.initialize() # exchanges JWT for a Slike session token
print(client.token) # resolved Slike session token
Provide exactly one of token or denmark_token.
Methods
initialize()
Validates credentials. Must be called once before any other method.
client.initialize()
register_media
Register media on Slike. Provide exactly one of file_path (chunked upload) or editor_settings (editor-generated video — no bytes uploaded).
Blocking file upload (waits for all chunks to finish):
result = client.register_media(
file_path="/path/to/video.mp4",
title="My Video",
description="Description",
asset_type="video", # optional, default: "video"
tags=["news", "sports"], # optional
preset_config={"meta": "", "social": ""}, # optional
team="team-id", # optional, team ID from get_required_metadata
business="biz-id", # optional, business ID paired with team
agency="agency-id", # optional, agency ID from get_agency_list
on_progress=lambda done, total: print(f"{done}/{total} chunks"),
)
print("Media ID:", result["id"])
Pass team and its paired business together — both come from the same team object returned by get_required_metadata:
meta = client.get_required_metadata()
selected_team = meta["default_team"]["team"] # or whichever team the user picks
result = client.register_media(
file_path="/path/to/video.mp4",
title="My Video",
description="Description",
team=selected_team["value"],
business=selected_team["business"],
)
Non-blocking file upload (upload runs in a background thread; callback fires the moment chunks finish):
def on_done(res, err):
if err:
print("Upload failed:", err)
else:
print("Upload complete! ID:", res["id"])
result = client.register_media(
file_path="/path/to/video.mp4",
title="My Video",
description="Description",
on_upload_complete=on_done, # fires immediately when chunks finish
)
# result["id"] is available right away — no need to wait
print("Registered, ID:", result["id"])
Editor video (no file — server renders from spec):
client.register_media(
title="My Editor Video",
description="Description",
tags=["news", "sports"],
editor_settings={
"source_width": 1080,
"source_height": 1920,
"clips": [...],
"background_music": {...},
},
)
get_status
Get basic media details and processing readiness by media ID.
status = client.get_status("media_id_here")
print(status["media_id"]) # media ID
print(status["title"]) # media title
print(status["desc"]) # media description
print(status["tags"]) # list of tags
print(status["status"]) # raw status code
print(status["is_ready"]) # True when status==5 and state==10
print(status["msg"]) # "Media is ready." or "Media is not ready yet."
Media is ready when is_ready is True (status == 5 and state == 10).
cancel
Cancel all in-progress background uploads on this client (local abort only).
import threading
result = client.register_media(
file_path="/path/to/video.mp4",
title="My Video",
description="Description",
on_upload_complete=lambda res, err: print("cancelled" if isinstance(err, CancelError) else err or res["id"]),
)
# Cancel from a UI button handler or another thread:
threading.Timer(5.0, client.cancel).start()
cancel() is a no-op if nothing is in progress. All background uploads on the client are stopped; retry backoff sleeps are woken immediately.
get_required_metadata
Fetch all dropdown options for building a media-update form. Returns static constants at the top level, per-team filtered languages and categories, and a flat agency list.
meta = client.get_required_metadata()
# Static constants (from SDK)
print(meta["content_types"]) # [{"value": "package", "label": "Package"}, ...]
print(meta["production_types"]) # [{"value": "In House Originals", "label": "In House Originals"}, ...]
print(meta["content_ratings"]) # [{"value": "1", "label": "Made for Kids"}, ...]
print(meta["media_states"]) # [{"value": 0, "label": "Draft"}, ...]
# Agencies (flat list sorted by recent activity)
for agency in meta["agencies"]:
print(agency["id"], agency["name"])
# Default team (pre-select on load); None if no teams exist
print(meta["default_team"]["team"]) # {"value": "team-id-1", "label": "Team 1", "is_default": True, "business": "biz-id"}
print(meta["default_team"]["languages"]) # [{"value": "Language 1", "label": "Language 1"}, ...]
print(meta["default_team"]["categories"]) # [{"value": "Category 1", "label": "Category 1", "subcategories": [...]}, ...]
# All teams (populate team switcher)
for entry in meta["teams"]:
print(entry["team"]) # {"value": ..., "label": ..., "is_default": ..., "business": ...}
print(entry["languages"]) # languages allowed for this team
print(entry["categories"]) # categories allowed for this team
get_agency_list
List active agencies, optionally filtered by name. Returns up to 50 results sorted by recent activity.
# All active agencies
result = client.get_agency_list()
print(result["count"]) # total count
for a in result["list"]:
print(a["id"], a["name"])
# Search by name
result = client.get_agency_list(name="toi")
| Parameter | Type | Description |
|---|---|---|
name |
str |
Optional name filter |
update_media
Update metadata fields on an existing media item. All fields except id are optional — only provided fields are sent.
result = client.update_media(
id="media-id-here",
title="Updated Title",
desc="Updated description",
tags=["news", "sports"],
lang="English",
category="News",
subcategory="Politics",
ctype="story",
production_type="In House Originals",
mfk=2, # content rating: 1=Kids, 2=General, 3=18+
media_state=1, # 0=Draft, 1=Active
expiry="2026-12-31",
youtube_id="dQw4w9WgXcQ",
parentid="parent-id",
)
print(result) # dict with updated media fields
| Parameter | Type | Description |
|---|---|---|
id |
str |
Required. Media ID to update |
title |
str |
Required. Media title |
title_url |
str |
URL-friendly title slug |
desc |
str |
Description |
tags |
list[str] |
Tags |
agency_credits |
list[str] |
Agency credits |
ctype |
str |
Content type (see CONTENT_TYPES) |
production_type |
str |
Production type (see PRODUCTION_TYPES) |
lang |
str |
Language name |
category |
str |
Category name |
subcategory |
str |
Sub-category name |
mfk |
int |
Content rating: 1=Kids, 2=General, 3=18+ |
images |
dict |
Image metadata |
expiry |
str |
Expiry date string |
youtube_id |
str |
YouTube video ID |
parentid |
str |
Parent media ID |
media_state |
int |
0=Draft, 1=Active |
cancel_upload
Cancel a specific upload and notify the Slike server to mark the media as cancelled (calls media.update with cancel status values). Use this when the user explicitly cancels from the UI.
result = client.register_media(
file_path="/path/to/video.mp4",
title="My Video",
description="Description",
on_upload_complete=lambda res, err: print(err or "done"),
)
media_id = result["id"]
# When user clicks Cancel in the UI:
client.cancel_upload(media_id)
This performs two actions atomically:
- Stops all local chunk upload threads
- Calls
media.updateon the Slike server to mark the media as cancelled
publish_media
Publish media by URL (Google Drive, YouTube, direct link).
client.publish_media(
url="https://drive.google.com/file/d/FILE_ID/view",
title="My Video",
description="Description",
type="gdrive", # gdrive | youtube | url
asset_type="video", # optional
tags=["news", "sports"], # optional
auto_publish=True, # optional, default: True
)
create_user
Create a CMS user. Send only name, email and team (a list of team ids);
the backend fills in all remaining user defaults. Calls the user.createcms RPC
on the accounts endpoint (https://accounts.sli.ke/rpc, dev
https://accounts-dev.sli.ke/rpc).
result = client.create_user(
name="Test User",
email="test.user@example.com",
team=["nd78ug9zoo", "ndbxuuzzko"],
)
Returns a concise confirmation:
{
"id": "ws41sgoouo",
"name": "Test User",
"email": "test.user@example.com",
"msg": "User 'Test User' created successfully with id ws41sgoouo.",
}
Equivalent raw request (same call the SDK makes):
curl -X POST https://accounts.sli.ke/rpc \
-H "Content-Type: application/json" \
--cookie "token=<YOUR_SLIKE_TOKEN>" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "user.createcms",
"params": {
"name": "Test User",
"email": "test.user@example.com",
"team": ["nd78ug9zoo", "ndbxuuzzko"]
}
}'
Dev uses https://accounts-dev.sli.ke/rpc with cookie token-dev=<...>. The token
may also be sent as a token header (-H "token: <...>") — the JS SDK uses the
header form. The raw reply is {"result": {"id": "...", ...}}.
get_teams_by_host
List the teams attached to a host. Calls the team.byhost RPC on the same
accounts endpoint. Multiple teams can share a host, so the result is always a list.
teams = client.get_teams_by_host(hostid="153")
for t in teams:
print(t["id"], t["name"], t["hostid"])
| Parameter | Type | Description |
|---|---|---|
hostid |
str |
Host id to look up (required) |
Returns a list of { "id", "name", "hostid" }:
[
{"id": "nd78ug9zoo", "name": "Team A", "hostid": "153"},
{"id": "ndbxuuzzko", "name": "Team B", "hostid": "153"},
]
Error handling
from slike import SlikeMedia, SlikeAPIError, CancelError
try:
client = SlikeMedia(token="...", environment="prod")
client.initialize()
result = client.register_media(file_path="video.mp4", title="T", description="D")
except ValueError as e:
print(f"Bad input: {e}")
except CancelError:
print("Upload was cancelled")
except SlikeAPIError as e:
print(f"API error: {e} (code: {e.code})")
if e.conflicts:
for c in e.conflicts:
print(f" conflict: field={c['field']} id={c['id']} value={c['value']}")
Duplicate file (unique constraint)
When a file with the same fid (derived from filename + size) is already registered on the server, register_media raises SlikeAPIError with conflicts populated:
except SlikeAPIError as e:
if e.conflicts:
# File already exists — e.conflicts[0]["id"] is the existing media ID
existing_id = e.conflicts[0]["id"]
print(f"Already uploaded as media ID: {existing_id}")
else:
print(f"API error: {e} (code: {e.code})")
SlikeAPIError fields:
| Field | Type | Description |
|---|---|---|
message |
str |
Human-readable error message |
code |
int | None |
HTTP or RPC error code (e.g. 400) |
conflicts |
list[dict] | None |
Conflict entries when a unique constraint is violated |
Each conflict entry has field, id, and value keys.
TypeScript / JavaScript SDK
Quick start
import { SlikeMedia } from 'slike';
const client = new SlikeMedia({ token: 'your-slike-token', environment: 'prod' });
await client.initialize();
// Upload a file (blocking — waits for all chunks)
const result = await client.uploadMedia({
file, // File object
title: 'My Video',
description: 'Description',
onProgress: (done, total) => console.log(`${done}/${total} chunks`),
});
console.log('Media ID:', result.id);
Denmark JWT auth
const client = new SlikeMedia({
denmarkToken: '<jwt>',
service: 'slike', // optional
environment: 'prod',
});
await client.initialize();
console.log(client.token);
Methods
initialize()
await client.initialize();
uploadMedia(opts) — blocking upload
Registers and uploads all chunks. Returns when complete.
const result = await client.uploadMedia({
file,
title: 'My Video',
description: 'Description',
tags: ['news', 'sports'],
team: 'team-id', // optional — from getRequiredMetadata
business: 'biz-id', // optional — paired with team
agency: 'agency-id', // optional — from getAgencyList
onProgress: (done, total) => console.log(`${done}/${total}`),
signal: abortController.signal, // optional AbortSignal
});
Pass team and business together — both come from the same team object:
const meta = await client.getRequiredMetadata();
const selectedTeam = meta.defaultTeam?.team; // or whichever team the user picks
const result = await client.uploadMedia({
file,
title: 'My Video',
description: 'Description',
team: selectedTeam?.value,
business: selectedTeam?.business,
});
uploadMediaBackground(opts) — non-blocking upload
Returns an UploadHandle immediately. onUploadComplete fires the moment chunks finish — caller does not need to wait.
const handle = await client.uploadMediaBackground({
file,
title: 'My Video',
description: 'Description',
onProgress: (done, total) => console.log(`${done}/${total}`),
onUploadComplete: (result, error) => {
if (error) console.error('Upload failed:', error);
else console.log('Upload complete! ID:', result.id);
},
});
console.log('Media ID (available now):', handle.mediaId);
// Cancel from UI — stops chunks locally AND marks media cancelled on Slike server:
cancelButton.onclick = () => handle.cancel();
// Or await completion:
const result = await handle.completion;
UploadHandle:
| Property | Type | Description |
|---|---|---|
mediaId |
string |
Media ID (available immediately) |
cancel() |
() => void |
Abort chunks + notify Slike server |
completion |
Promise<RegisterMediaResult> |
Resolves when upload finishes |
getStatus(mediaId, signal?)
Get basic media details and processing readiness.
const status = await client.getStatus('media_id_here');
console.log(status.mediaId); // media ID
console.log(status.title); // media title
console.log(status.desc); // media description
console.log(status.tags); // string[] | undefined
console.log(status.status); // raw status code
console.log(status.isReady); // true when status===5 and state===10
console.log(status.msg); // "Media is ready." or "Media is not ready yet."
getRequiredMetadata(signal?)
Fetch all dropdown options for building a media-update form. Returns static constants at the top level, per-team filtered languages and categories, and a flat agency list.
const meta = await client.getRequiredMetadata();
// Static constants (from SDK)
console.log(meta.contentTypes); // [{ value: 'package', label: 'Package' }, ...]
console.log(meta.productionTypes); // [{ value: 'In House Originals', label: 'In House Originals' }, ...]
console.log(meta.contentRatings); // [{ value: '1', label: 'Made for Kids' }, ...]
console.log(meta.mediaStates); // [{ value: 0, label: 'Draft' }, ...]
// Agencies (flat list sorted by recent activity)
console.log(meta.agencies); // [{ id: 'agency-id', name: 'Agency Name' }, ...]
// Default team (pre-select on load)
console.log(meta.defaultTeam.team); // { value: 'team-id-1', label: 'Team 1', is_default: true, business: 'biz-id' }
console.log(meta.defaultTeam.languages); // [{ value: 'language-1', label: 'Language 1' }, ...]
console.log(meta.defaultTeam.categories); // [{ value: 'category-1', label: 'Category 1', subcategories: [...] }, ...]
// All teams (populate team switcher)
meta.teams.forEach(({ team, languages, categories }) => {
console.log(team); // { value, label, is_default, business }
console.log(languages); // languages allowed for this team
console.log(categories); // categories allowed for this team
});
You can also import the static constants directly:
import { CONTENT_TYPES, PRODUCTION_TYPES, CONTENT_RATINGS, MEDIA_STATES } from 'slike';
Example response:
{
"contentTypes": [{ "value": "content-type-1", "label": "Content Type 1" }],
"productionTypes": [{ "value": "production-type-1", "label": "Production Type 1" }],
"contentRatings": [{ "value": "1", "label": "Rating 1" }],
"mediaStates": [{ "value": 0, "label": "State 1" }],
"agencies": [{ "id": "agency-id-1", "name": "Agency Name" }],
"defaultTeam": {
"team": { "value": "team-id-1", "label": "Team 1", "is_default": true, "business": "biz-id-1" },
"languages": [{ "value": "language-1", "label": "Language 1" }],
"categories": [{ "value": "category-1", "label": "Category 1", "subcategories": [{ "value": "sub-category-1", "label": "Sub Category 1" }] }]
},
"teams": [
{
"team": { "value": "team-id-1", "label": "Team 1", "is_default": true, "business": "biz-id-1" },
"languages": [{ "value": "language-1", "label": "Language 1" }],
"categories": [{ "value": "category-1", "label": "Category 1", "subcategories": [] }]
},
{
"team": { "value": "team-id-2", "label": "Team 2", "is_default": false, "business": "biz-id-1" },
"languages": [{ "value": "language-1", "label": "Language 1" }],
"categories": [{ "value": "category-1", "label": "Category 1", "subcategories": [{ "value": "sub-category-1", "label": "Sub Category 1" }] }]
}
]
}
getAgencyList(opts?, signal?)
List active agencies, optionally filtered by name. Returns up to 50 results sorted by recent activity.
// All active agencies
const result = await client.getAgencyList();
console.log(result.count); // total count
console.log(result.list); // [{ id: 'agency-id', name: 'Agency Name' }, ...]
// Search by name
const byName = await client.getAgencyList({ name: 'toi' });
AgencySearchOptions:
| Field | Type | Description |
|---|---|---|
name |
string |
Optional name filter |
AgencyListResult: { list: AgencyOption[]; count: number }
AgencyOption: { id: string; name: string }
updateMedia(opts, signal?)
Update metadata fields on an existing media item. All fields except id are optional.
const result = await client.updateMedia({
id: 'media-id-here',
title: 'Updated Title',
desc: 'Updated description',
tags: ['news', 'sports'],
lang: 'English',
category: 'News',
subcategory: 'Politics',
ctype: 'story',
productionType: 'In House Originals',
mfk: 2, // content rating: 1=Kids, 2=General, 3=18+
media_state: 1, // 0=Draft, 1=Active
expiry: '2026-12-31',
youtube_id: 'dQw4w9WgXcQ',
parentid: 'parent-id',
});
UpdateMediaOptions:
| Field | Type | Description |
|---|---|---|
id |
string |
Required. Media ID to update |
title |
string |
Required. Media title |
title_url |
string |
URL-friendly title slug |
desc |
string |
Description |
tags |
string[] |
Tags |
agency_credits |
string[] |
Agency credits |
ctype |
string |
Content type (see CONTENT_TYPES) |
productionType |
string |
Production type (see PRODUCTION_TYPES) |
lang |
string |
Language name |
category |
string |
Category name |
subcategory |
string |
Sub-category name |
mfk |
number |
Content rating: 1=Kids, 2=General, 3=18+ |
images |
object |
Image metadata |
expiry |
string |
Expiry date string |
youtube_id |
string |
YouTube video ID |
parentid |
string |
Parent media ID |
media_state |
0 | 1 |
0=Draft, 1=Active |
cancelUpload(mediaId, signal?)
Mark a specific media as cancelled on the Slike server (calls media.update with cancel status values). Use when the user explicitly cancels from the UI and you need the server to reflect that.
await client.cancelUpload('media_id_here');
Note:
UploadHandle.cancel()already calls this automatically. UsecancelUpload()directly only when you have amediaIdwithout a handle (e.g. cancelling a previously registered upload on page reload).
publishMedia(opts)
await client.publishMedia({
url: 'https://drive.google.com/file/d/FILE_ID/view',
title: 'My Video',
description: 'Description',
type: 'gdrive', // 'gdrive' | 'youtube' | 'url'
tags: ['news', 'sports'],
autoPublish: true,
});
createUser(opts, signal?)
Create a CMS user. Provide only name, email and team (an array of team ids);
the backend fills in all remaining user defaults. Calls the user.createcms RPC
on the accounts endpoint (https://accounts.sli.ke/rpc, dev
https://accounts-dev.sli.ke/rpc).
const result = await client.createUser({
name: 'Test User',
email: 'test.user@example.com',
team: ['nd78ug9zoo', 'ndbxuuzzko'],
});
Returns a concise confirmation:
{
id: 'ws41sgoouo',
name: 'Test User',
email: 'test.user@example.com',
msg: "User 'Test User' created successfully with id ws41sgoouo.",
}
getTeamsByHost(hostid, signal?)
List the teams attached to a host. Calls the team.byhost RPC on the same
accounts endpoint. Multiple teams can share a host, so the result is always an array.
const teams = await client.getTeamsByHost('153');
// [{ id: 'nd78ug9zoo', name: 'Team A', hostid: '153' }, ...]
| Parameter | Type | Description |
|---|---|---|
hostid |
string |
Host id to look up (required) |
signal |
AbortSignal |
Optional abort signal |
Returns HostTeam[] — a list of { id, name, hostid }.
Error handling (TypeScript)
import { SlikeMedia, SlikeAPIError, CancelError } from 'slike';
try {
await client.uploadMedia({ file, title: 'T', description: 'D' });
} catch (err) {
if (err instanceof CancelError) {
console.log('Upload cancelled');
} else if (err instanceof SlikeAPIError) {
console.error('API error:', err.message, 'code:', err.code);
if (err.conflicts) {
for (const c of err.conflicts) {
console.log(`conflict: field=${c.field} id=${c.id} value=${c.value}`);
}
}
}
}
Duplicate file (unique constraint)
When a file with the same fid is already registered, registerMedia throws SlikeAPIError with the message "This file has already been uploaded…" and conflicts populated:
import { SlikeAPIError, type ConflictEntry } from 'slike';
try {
await client.registerMedia({ file, title: 'T', description: 'D' });
} catch (err) {
if (err instanceof SlikeAPIError && err.conflicts) {
// File already exists — err.conflicts[0].id is the existing media ID
const existing = err.conflicts[0];
console.log(`Already uploaded as media ID: ${existing.id}`);
}
}
SlikeAPIError fields:
| Field | Type | Description |
|---|---|---|
message |
string |
Human-readable error message |
code |
number | undefined |
HTTP or RPC error code (e.g. 400) |
conflicts |
ConflictEntry[] | undefined |
Conflict entries when a unique constraint is violated |
ConflictEntry fields: field, id, value.
Use Cases
1. Upload a file and check status after
# Python
client.initialize()
result = client.register_media(file_path="video.mp4", title="T", description="D")
status = client.get_status(result["id"])
print(status["msg"]) # "Media is not ready yet." (processing takes time)
// TypeScript
await client.initialize();
const result = await client.uploadMedia({ file, title: 'T', description: 'D' });
const status = await client.getStatus(result.id);
console.log(status.msg); // "Media is not ready yet."
2. Background upload with completion callback + cancel from UI
# Python
result = client.register_media(
file_path="video.mp4",
title="My Video",
description="Description",
on_upload_complete=lambda res, err: (
print("failed:", err) if err else print("ready to process, ID:", res["id"])
),
)
# Store media_id for potential cancel
media_id = result["id"]
# When user clicks Cancel:
client.cancel_upload(media_id)
// TypeScript
const handle = await client.uploadMediaBackground({
file,
title: 'My Video',
description: 'Description',
onUploadComplete: (result, error) => {
if (error) console.error('failed:', error);
else console.log('chunks done, media processing started:', result.id);
},
});
// Wire to UI cancel button — aborts chunks AND marks cancelled on server:
cancelBtn.onclick = () => handle.cancel();
3. Check if media is ready before serving
# Python
status = client.get_status(media_id)
if status["is_ready"]:
print("Serve URL from your CDN using media_id:", status["media_id"])
else:
print(status["msg"])
// TypeScript
const status = await client.getStatus(mediaId);
if (status.isReady) {
serveMedia(status.mediaId);
} else {
showMessage(status.msg);
}
4. Cancel a previously registered upload (e.g. on page reload)
// If you stored the mediaId in localStorage before the page unloaded:
const mediaId = localStorage.getItem('pendingMediaId');
if (mediaId) {
await client.cancelUpload(mediaId);
localStorage.removeItem('pendingMediaId');
}
Configuration (CLI / Python only)
Priority (highest wins)
- CLI flags (
--token,--denmark-token,--env,--config) - Environment variables (
SLIKE_TOKEN,SLIKE_ENVIRONMENT,SLIKE_CONFIG) ./config.toml→~/.slike/config.toml
Config file
token = "your-token-here"
environment = "prod" # "dev" or "prod"
Environment variables
| Variable | Description |
|---|---|
SLIKE_TOKEN |
Slike auth token |
SLIKE_ENVIRONMENT |
dev or prod |
SLIKE_CONFIG |
Path to a specific config file |
CLI
# Upload a local file
slike-upload video.mp4 --title "My Video" --desc "Description"
# Publish by URL (Google Drive)
slike-upload --url https://drive.google.com/file/d/FILE_ID/view \
--type gdrive --title "My Video" --desc "Description"
# Denmark JWT auth
slike-upload video.mp4 --title "T" --desc "D" --denmark-token <jwt>
| Flag | Description |
|---|---|
--url |
Media URL to ingest (publish mode) |
--type |
gdrive, youtube, or url (default: url) |
--title |
Media title |
--desc |
Media description |
--asset-type |
e.g. video, shorts (default: video) |
--tags |
Comma-separated tags |
--no-publish |
Save as draft, skip auto-publish |
--token |
Slike auth token |
--denmark-token |
Denmark JWT (exchanged for a Slike session token) |
--service |
Service name for Denmark auth (default: slike) |
--env |
dev or prod |
--config |
Path to config file |
Environments
| Environment | RPC endpoint | Upload endpoint | Auth endpoint |
|---|---|---|---|
prod |
https://b2b.sli.ke/rpc |
https://asset.sli.ke/upload |
https://accounts.sli.ke/login |
dev |
https://app-dev.sli.ke/rpc |
https://asset-dev.sli.ke/upload |
https://accounts-dev.sli.ke/login |
How it works
Auth (initialize()):
token: callsuser.meRPC to verify validity.denmark_token: POSTs{type: 4, jwt, service}to/login, readsdata.token.
Chunked file upload:
media.registerRPC → returnsmedia_id+ short-lived upload JWT- File split into 4 MiB chunks, each POSTed as
multipart/form-data - Failed chunks retry up to 3 times with exponential backoff (interruptible by cancel)
Editor video: media.register with type: "videoeditor" + editor spec. No bytes uploaded.
Status check (get_status / getStatus): calls media.get RPC, returns shaped object with is_ready (status==5 AND state==10) and a human-readable msg.
Cancel upload (cancel_upload / cancelUpload): stops local chunk threads and calls media.update RPC with status=-2, state=-2, media_status=-1 to mark the media cancelled on the server.
Required metadata (get_required_metadata / getRequiredMetadata): fires batch.lists (keys: ["language", "category", "team"]) and agency.list in parallel. Filters languages and categories to status === 1, groups them per team using each team's meta.language and meta.category ID allowlists, and surfaces business (business ID) on each team. Returns agencies (flat [{id, name}] list), defaultTeam (team with is_default: true), all teams with their filtered dropdowns, and static SDK constants at the top level.
Agency list (get_agency_list / getAgencyList): calls agency.list RPC with a standard descending sort by activity. Adds a must filter only when name or status is provided.
Media update (update_media / updateMedia): calls media.update RPC with only the fields you provide — omitted fields are not sent.
Development
git clone <repo>
cd slike-media-package
# Python
python3 -m pip install -e .
python3 -m unittest test_slike -v
# TypeScript
cd js
npm install
npx tsc --noEmit # type-check
npm run build # compile to dist/
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file slike-0.2.2.tar.gz.
File metadata
- Download URL: slike-0.2.2.tar.gz
- Upload date:
- Size: 35.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ccea69a77a588f8d8da4529b3c8eb29fa357498965801b5c5b61d711c6d04330
|
|
| MD5 |
b7b3eadf74d943aa31b8c556bb11fe20
|
|
| BLAKE2b-256 |
359572d1bf14acbb6b8d8abe4f4b788e661965134dceafa2820364bc7b82e95f
|
File details
Details for the file slike-0.2.2-py3-none-any.whl.
File metadata
- Download URL: slike-0.2.2-py3-none-any.whl
- Upload date:
- Size: 24.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bf4fbc6c6ef703c96e5071296f55ab28f58f8d0d2d0eebc99701ff491555c76f
|
|
| MD5 |
7ea145668f82c6cee46340c9a272a75a
|
|
| BLAKE2b-256 |
71884214df76b324520aaf9479d2818379e01991c3878cd496fb80b03f2f7412
|