Jukie
Integration Docs

Guild Embeds

Put a guild-owned Jukie library inside an authorized website or application. Jukie keeps media access scoped to one guild, measures active playback, and can send signed listening events back to your server.

Server-signed accessGuild-isolated mediaResponsive player

How it works

  1. Your server authenticates the listener.Never place the shared signing secret in browser code.
  2. Your server creates a short-lived player token.The token identifies the external user, guild library, scopes, and session.
  3. Your page embeds the Jukie player.Jukie validates the token before listing or streaming any track.
  4. Jukie reports measured listening.Optional signed webhooks are idempotent and safe to retry.

Jukie configuration

Configure approved guilds, parent origins, and the optional listening webhook in Jukie's protected environment.

JUKIE_INTEGRATION_SHARED_SECRET=replace-with-a-long-random-secret
JUKIE_INTEGRATION_GUILD_IDS=123456789012345678
JUKIE_INTEGRATION_EMBED_ORIGINS=https://community.example
JUKIE_LISTENING_WEBHOOK_URL=https://community.example/api/jukie/listening
Keep the secret server-side.The consuming application and Jukie share it. The browser receives only a signed, expiring token.

Create a signed token

Tokens use URL-safe base64 JSON and an HMAC-SHA256 signature. Generate a new jti for every player session and keep expiry short.

import base64, hashlib, hmac, json, secrets, time

now = int(time.time())
claims = {
    "aud": "jukie-player",
    "iss": "your-app",
    "sub": "your-listener-id",
    "guild_id": "123456789012345678",
    "jti": secrets.token_urlsafe(24),
    "iat": now,
    "exp": now + 3600,
    "scopes": ["player", "listening", "timeline_cues"],
    "theme": "dark",
    "library_label": "Community Radio",
    "parent_origin": "https://community.example",
}

payload = base64.urlsafe_b64encode(
    json.dumps(claims, separators=(",", ":"), sort_keys=True).encode()
).decode().rstrip("=")
signature = base64.urlsafe_b64encode(
    hmac.new(SHARED_SECRET.encode(), payload.encode(), hashlib.sha256).digest()
).decode().rstrip("=")
token = f"{payload}.{signature}"
ClaimPurpose
subYour stable listener identifier.
guild_idThe single Jukie library this session may access.
jtiA unique player session identifier.
scopesMust contain player; add listening for progress and timeline_cues for real-time cue messages.
themedark, rose, or light.

Embed the player

Return the final URL from your authenticated backend, then assign it directly to the iframe. Do not place a protected redirect inside the frame.

<iframe
  title="Community audio player"
  src="https://jukie.app/integrations/v1/player?token=SIGNED_TOKEN"
  allow="autoplay"
  loading="lazy">
</iframe>

The player is responsive and supports native audio controls, track selection, shuffle, byte-range streaming, and the signed theme supplied by your server.

With timeline_cues, the player sends jukie.timeline-cue messages to the signed parent_origin as its audio clock crosses each neutral cue. Validate event.origin before acting. Use this channel for time-sensitive integrations; do not wait for listening-credit webhooks.

Media sources

Normal paid guilds use isolated hosted storage and retain uploads, subscription quotas, playlists, and Discord controls. Trusted self-hosted installations may additionally map a guild to an existing server folder.

JUKIE_GUILD_MEDIA_PATHS=123456789012345678=/srv/audio/community

Supported audio is indexed without copying it. Matching JSON sidecars may provide neutral audio_file and length_ms metadata; provider-specific fields are ignored. Remote services should be implemented as media-source adapters only when their supported API and licensing permit it.

Listening webhooks

When configured, Jukie sends compact JSON events signed over the exact request body. Verify X-Jukie-Signature with HMAC-SHA256 before accepting an event.

{
  "provider": "jukie",
  "external_user_id": "external-listener-id",
  "event_id": "session-id:heartbeat-id",
  "seconds": 15,
  "track_id": "42"
}

Store event_id uniquely so retries cannot grant credit twice. Jukie measures heartbeat intervals server-side; consuming applications should never trust browser-submitted elapsed time.

Security checklist

  • Authenticate listeners before issuing tokens.
  • Use an unpredictable secret and rotate it deliberately.
  • Allow only the guilds and parent origins your integration needs.
  • Keep token lifetimes short and provide a visible disconnect control.
  • Verify webhook signatures with a constant-time comparison.
  • Reject expired, forged, replayed, or duplicate events.