ClippedDocs

Use case

Show new clips in your own app

Poll the clip feed with a cursor, keep every clip with its thumbnail, and play the video through your own server.

For a site, a Discord bot or an internal tool that lists clips as they are found. The feed is built for polling: every answer carries a cursor, and passing it back returns only what happened since, so nothing is seen twice and nothing is missed.

  1. 1Poll with a cursor

    The first call, with no cursor, returns the newest few and a cursor to continue from. Keep the cursor somewhere that survives a restart.

    A clip comes back again when it changes: when it is cut, titled, posted, or when its thumbnail is made. So store clips by id and overwrite.

    A polling loop (Node 18+)JavaScript
    const API = "https://app.clipped.so/api/v1"
    const headers = { Authorization: `Bearer ${process.env.CLIPPED_KEY}` }
    
    let cursor = await loadCursor() // wherever you keep it; undefined the first time
    
    while (true) {
      const query = new URLSearchParams({ limit: "100" })
      if (cursor) query.set("cursor", cursor)
      const page = await (await fetch(`${API}/clips?${query}`, { headers })).json()
    
      for (const clip of page.clips) await saveClip(clip) // by clip.id: the same clip returns when it changes
      cursor = page.cursor
      await saveCursor(cursor)
    
      await new Promise((r) => setTimeout(r, 10_000))
    }
  2. 2Show the thumbnail

    thumbnail is a public image address: put it straight in an <img>, no key needed. It is null until the still is made, a moment after a clip is cut or a few minutes after an uncut one is found, and the clip comes back in the feed when it arrives.

    To have one sooner, ask for it from your server: GET /api/v1/clips/{id}/thumbnail makes it if it can and redirects to the image, or answers 202 with Retry-After when the footage isn't there yet.

    Shell
    curl -L "https://app.clipped.so/api/v1/clips/$CLIP_ID/thumbnail" -H "Authorization: Bearer $KEY" -o thumbnail.webp
  3. 3Play the video

    video needs your key, so a browser can't load it directly: fetch it from your server and pass the bytes on. It is an mp4 and supports Range, so a player can seek.

    Most clips are cut only when somebody asks. If cut is uncut, the first fetch of video starts the cut and answers 202 with Retry-After; ask again and the mp4 is there, usually within a minute.

    Passing a clip through your own serverJavaScript
    export async function GET(request, { params }) {
      const upstream = await fetch(`https://app.clipped.so/api/v1/clips/${encodeURIComponent(params.id)}/video`, {
        headers: { Authorization: `Bearer ${process.env.CLIPPED_KEY}`, Range: request.headers.get("range") ?? "" },
      })
      // 202: still being cut. Tell your player to try again shortly.
      return new Response(upstream.body, { status: upstream.status, headers: upstream.headers })
    }

Worth knowing

  • A clip id contains a colon. URL-encode it in a path.
  • ?channel= narrows the feed to one streamer.
  • Polling every ten seconds is 8,640 calls a day. The limits for your plan are on GET /api/v1/me; a webhook costs none.