Skip to main content

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:

  1. Stops all local chunk upload threads
  2. Calls media.update on 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. Use cancelUpload() directly only when you have a mediaId without 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)

  1. CLI flags (--token, --denmark-token, --env, --config)
  2. Environment variables (SLIKE_TOKEN, SLIKE_ENVIRONMENT, SLIKE_CONFIG)
  3. ./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: calls user.me RPC to verify validity.
  • denmark_token: POSTs {type: 4, jwt, service} to /login, reads data.token.

Chunked file upload:

  1. media.register RPC → returns media_id + short-lived upload JWT
  2. File split into 4 MiB chunks, each POSTed as multipart/form-data
  3. 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

slike-0.2.2.tar.gz (35.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

slike-0.2.2-py3-none-any.whl (24.4 kB view details)

Uploaded Python 3

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

Hashes for slike-0.2.2.tar.gz
Algorithm Hash digest
SHA256 ccea69a77a588f8d8da4529b3c8eb29fa357498965801b5c5b61d711c6d04330
MD5 b7b3eadf74d943aa31b8c556bb11fe20
BLAKE2b-256 359572d1bf14acbb6b8d8abe4f4b788e661965134dceafa2820364bc7b82e95f

See more details on using hashes here.

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

Hashes for slike-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 bf4fbc6c6ef703c96e5071296f55ab28f58f8d0d2d0eebc99701ff491555c76f
MD5 7ea145668f82c6cee46340c9a272a75a
BLAKE2b-256 71884214df76b324520aaf9479d2818379e01991c3878cd496fb80b03f2f7412

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page