Livestream Clipping API: Running a Live Clip Session
Most video APIs give you a job. A livestream clipping API gives you a subscription — a running session, identified by a subscriptionId, that stays attached to a broadcast that has not finished yet. That single difference is what this page is about. Everything awkward in a live integration comes from the fact that you are now holding a handle to something that is still happening, and handles have to be opened, watched, renewed, and closed.
ClipSpeedAI exposes live mode through its MCP server at https://api.clipspeed.ai/mcp. Four tools cover the session itself: clip_livestream opens one and hands back a subscriptionId; check_livestream polls that id and reports status, where monitoring means the stream is still live and still being clipped; extend_livestream keeps an active session going; and stop_livestream closes it, with clips already produced kept and still downloadable. Two more tools pick up on the other side: check_clips returns finished, scored, captioned 9:16 clips for a project, and publish_to_youtube pushes a chosen one out, defaulting to private.
What follows is a working integration, in the order you actually build one: the lifecycle first, then keys, then a curl sequence that runs as printed because it carries the session header, then a Python supervisor loop, then the parts that break. If you have not clipped a recorded video through this server yet, do that first — Video Clipping API for Developers walks the simpler path, and there is no reason to debug session management and clip quality at the same time.
A Session Is a Handle You Are Holding Open
Submitting a recorded video is a request-response shape with a long tail: you hand over a URL, the server works, you collect a finished set. Nothing you did stays alive. Live mode inverts that. clip_livestream returns a subscriptionId, and from that instant your integration owns something that exists on both sides of the connection until one of you ends it.
Three consequences follow, and they drive every design decision further down this page.
- The result set is never final. Every read of the clip list is accurate and incomplete at the same time. There is no moment during the broadcast when you can say "that is all of them," because the source of clips has not stopped producing input.
- The identifier matters more than the payload. Lose the
subscriptionIdand you cannot poll, extend, or stop the thing you started. Treat it the way you would treat a lock token: persist it before you do anything else, not after your loop is working. - Closing is an action, not an outcome.
stop_livestreamexists because ending is a decision you make. The reassuring part, and it is worth knowing before you hesitate over the call: stopping keeps the clips already made, and they stay downloadable afterward. There is no penalty for stopping early beyond stopping early.
If you want the request-response shape instead, that is submit_to_clipspeed — the recorded path, covered in AI Clipping API: Programmatic Short-Form Video. Nothing on this page applies to it, which is exactly why live clipping gets its own four tools instead of a flag.
The Four Live Calls, Drawn as Transitions
It helps to stop thinking of these as endpoints and start thinking of them as edges in a small state machine. There are four of them and only one creates state.
| Call | Moves you | Carries | Notes |
|---|---|---|---|
clip_livestream | nothing → active session | the stream URL in, a subscriptionId back | The only state-creating call. Idempotency is your problem, not the server's — call it twice and you are supervising two sessions. |
check_livestream | active → active (a read) | subscriptionId | Reports session status. monitoring is the healthy live state: stream still on air, clipping still happening. |
extend_livestream | active → active, renewed | subscriptionId | Extends a session that is currently active. Read the tool's own inputSchema for what else it accepts. |
stop_livestream | active → closed | subscriptionId | Ends the session deliberately. Clips already produced are kept and remain downloadable. |
Notice what is not in that table: retrieving clips. check_clips is keyed on a projectId, not on a subscription, and it is the same call the recorded path uses. So one of the first things to establish in your own account is how the identifier you were handed at session start relates to the project whose clips you want to read. Do not assume the two strings are interchangeable because they are both opaque — log the full result of check_livestream once, look at what came back, and wire your code to that. An agent client will resolve the hop for you; a script has to be told.
Keeping a live surface this small is a deliberate design choice, and the argument for small tool surfaces — that an agent picks correctly far more often when there are four obvious verbs than when there are fourteen overlapping ones — is made properly in MCP Tool Design: Writing Tools an Agent Can Actually Use.
Why a Six-Hour Tournament Cannot Be Ranked Like a Recording
Take a concrete case: an esports tournament broadcast that will run about six hours, with a long dead patch in the middle for a bracket reset, and the three moments anyone will care about landing in the final ninety minutes.
Given that broadcast as a file, selection is a comparison problem. Ranking is trivial because the population is complete.
Given the same broadcast live, none of that is available at the moment a decision has to be made:
- The population is a prefix. At minute forty, the only candidates that exist are the ones already broadcast.
- "Top ten" is not a computable question mid-stream. It becomes computable when the stream ends, at which point you have a recording and the recorded path applies.
- The source does not rewind. If ingest hiccups during a moment, that footage is not re-fetchable the way a VOD is re-downloadable.
- Runtime is unbounded. Six hours was an estimate. It might be nine. A session model with explicit extension exists precisely because "run until done" has no meaning here.
- Sentence boundaries are open at the edge. Deciding where a clip ends is easier when the sentence has already finished. Live, the last sentence in the window may still be in progress.
None of that is a defect in any particular product. It is the shape of the problem, and it is the list to interrogate when you evaluate any live clipping service — ask how each constraint is handled, not how modern the model is.
The Key: csai_live_, Shown Once, Revocable
Live sessions are long-running, which makes the credential behind them more interesting than usual. A key that authorizes a six-hour unattended loop is worth being precise about.
Generate one in the app under Account → API & Integrations → Generate API Key, which posts to POST /auth/api-keys. The key is the string csai_live_ followed by 48 hexadecimal characters — 24 random bytes, hex-encoded. Only the prefix is stored for display, so the full value appears once, at creation, and cannot be retrieved afterward. If you lose it, you issue a new one; there is no recovery path, by design.
GET /auth/api-keys lists the keys on the account with the fields that matter for a polling integration: name, key_prefix, plan, rate_limit, requests_today, total_requests, last_request_at, is_active, and created_at. That is unusually useful here. A live integration's request volume is dominated by its poll cadence, and rather than guessing whether a sixty-second loop is reasonable, you can run one session and read requests_today against rate_limit afterward. Measure the loop; do not theorise about it.
DELETE /auth/api-keys/:id revokes a key — it flips is_active to false and stamps a revocation time. Revocation being real changes how you should operate: issue a separate key per integration and per machine, name them so you can tell them apart in the list, and kill the one that leaked rather than rotating everything. A single shared key across a laptop, a CI runner, and a scheduled job is one key you cannot revoke without breaking three things.
Handle it like a password otherwise: environment variables, never committed, never in anything shipped to a browser. The wider reasoning about credential blast radius and what an agent should be allowed to reach lives in MCP Security: Scopes, Keys and Safe Tool Design, and the choice between a static bearer key and the OAuth path is worked through in MCP Authentication: OAuth and Bearer Keys.
Which Clients Are Verified, and at What Level
Support here is stated at the level it was actually tested, which is not always the level a compatibility matrix would imply. Three tiers:
| Tier | Clients | What the tier means |
|---|---|---|
| Fully supported | Claude (claude.ai), Claude Code, Claude Desktop, Windsurf | Verified end to end against the server. |
| Compatible | Cursor, Codex, OpenClaw, Hermes | Same protocol; verification is in progress rather than complete. |
| Rolling out | ChatGPT | Vendor-gated and unverified. |
Authentication splits by client type rather than by tier: GUI clients authorize over OAuth, and CLI clients send Authorization: Bearer <API_KEY>. For a CLI agent the whole wiring is one command:
claude mcp add --transport http clipspeed https://api.clipspeed.ai/mcp \ --header "Authorization: Bearer <API_KEY>"
That is the only client configuration reproduced verbatim on this page, and ClipSpeedAI MCP for Claude Code: Complete Setup Guide covers it in full. For any other client, the shape of the job is the same in prose: add ClipSpeedAI as an HTTP MCP server pointed at https://api.clipspeed.ai/mcp, with your key in the Authorization header, following that client's own MCP documentation for where its server list lives. Each client's setup guide on this site walks its specifics; config file names and field names differ between them and change between releases, so the vendor's documentation is the authority rather than anything printed here.
An npm package, clipspeed-mcp, also exists if a package-based install suits your environment better than a raw HTTP entry.
A curl Sequence That Runs as Printed
MCP over streamable HTTP is JSON-RPC 2.0 posted to one URL, so curl is a legitimate client. The part usually omitted from examples is the session header, which is exactly the part that makes a copy-pasted sequence fail on the second command. Here is the whole handshake with it wired in.
export CLIPSPEED_API_KEY="<API_KEY>" # csai_live_ + 48 hex chars
MCP="https://api.clipspeed.ai/mcp"
AUTH=(-H "Authorization: Bearer $CLIPSPEED_API_KEY" -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream") # 1. initialize, keeping the response headers
curl -sS -D /tmp/mcp-headers "$MCP" "${AUTH[@]}" -d '{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2025-06-18", "capabilities": {}, "clientInfo": { "name": "curl", "version": "1.0" } }
}' > /tmp/mcp-init # 2. pull the session id out of the headers, if the server issued one
SID=$(grep -i '^mcp-session-id:' /tmp/mcp-headers | awk '{print $2}' | tr -d '\r')
SESSION=()
[ -n "$SID" ] && SESSION=(-H "Mcp-Session-Id: $SID") # 3. tell the server the handshake is finished (a notification: no id, no reply)
curl -sS "$MCP" "${AUTH[@]}" "${SESSION[@]}" \ -d '{"jsonrpc":"2.0","method":"notifications/initialized"}'Two things to understand rather than copy. If no Mcp-Session-Id header comes back, $SID is empty and the SESSION array stays empty, so later calls simply go out without it — which is the correct behaviour, not a workaround. And responses may arrive as server-sent events rather than a plain JSON body, in which case each payload line is prefixed with data: and has to be stripped before parsing. That is what the sed below is for.
What the server does with that envelope once it lands — routing, tool dispatch, the response framing — is taken apart in How MCP Servers Work: Architecture and Request Flow.
Let the Schema Name the Arguments
Before writing a session driver, print the tool definitions. The server's own inputSchema is the authority on argument names; a page like this one is not, and schemas change without anyone updating prose.
curl -sS "$MCP" "${AUTH[@]}" "${SESSION[@]}" \ -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \ | sed -n 's/^data: //p' \ | jq '.result.tools[] | select(.name | test("livestream|clips")) | {name, description, inputSchema}'That prints the exact accepted fields, and the required array inside each schema, for clip_livestream, check_livestream, extend_livestream, stop_livestream and check_clips. Build request bodies from that output. A tool call is then tools/call with a name and an arguments object shaped to match:
curl -sS "$MCP" "${AUTH[@]}" "${SESSION[@]}" -d '{ "jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": { "name": "clip_livestream", "arguments": { } }
}' | sed -n 's/^data: //p' | jq .The empty arguments object is deliberate — fill it from the schema you just printed, not from an example. The same discipline applies to reading results: capture the full response from your first successful clip_livestream call and find where the subscriptionId actually sits in the content blocks before you write a parser around an assumed path.
A Python Supervisor for One Broadcast
For unattended work, use the official Python MCP SDK rather than shell. It handles the initialize handshake, the session header, and SSE framing, which removes most of the previous two sections from your codebase.
import asyncio, os
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client URL = "https://api.clipspeed.ai/mcp"
HEADERS = {"Authorization": f"Bearer {os.environ['CLIPSPEED_API_KEY']}"} STATUS_POLL_SEC = 60
CLIP_POLL_EVERY = 3 # read clips once every 3 status polls async def main(): async with streamablehttp_client(URL, headers=HEADERS) as (read, write, _): async with ClientSession(read, write) as session: await session.initialize() # Print the real schemas once; wire the calls below to them. for t in (await session.list_tools()).tools: print(t.name, "->", t.inputSchema) started = await session.call_tool("clip_livestream", {}) print("raw start result:", started.content) sub_id = extract_subscription_id(started) # yours to write persist(sub_id) # write it down NOW seen, tick = set(), 0 try: while True: tick += 1 status = await session.call_tool( "check_livestream", {"subscriptionId": sub_id}) state = extract_status(status) print("status:", state) if state != "monitoring": # No longer live-and-clipping. Read the real payload # before deciding whether to stop, extend, or wait. break if tick % CLIP_POLL_EVERY == 0: clips = await session.call_tool("check_clips", {}) for c in extract_clips(clips): key = clip_identity(c) if key not in seen: seen.add(key) handle_new_clip(c) await asyncio.sleep(STATUS_POLL_SEC) finally: await session.call_tool( "stop_livestream", {"subscriptionId": sub_id}) asyncio.run(main())The gaps are intentional and there are three kinds. The {} passed to clip_livestream is for you to fill from its printed schema. The extract_* helpers are yours because MCP tool results are content blocks and the useful fields sit wherever the server puts them — parse what actually comes back, not what you expected. And check_clips is called with an empty object here for the same reason discussed earlier: it is keyed on a project, so wire it to whatever identifier your first real run shows you.
Everything else is the pattern worth copying: initialize once, discover, start, persist the id immediately, poll status on a timer, read clips on a slower multiple of that timer, break on a status that is no longer monitoring, and put the teardown in finally so it runs on the exception path too.
Cadence, Identity, Teardown
Most of the engineering in a live integration sits in the loop rather than in the calls. Four habits cover it.
- Give the loop a generous floor. A minute between status polls is reasonable. Rendering a clip takes real compute, so polling every few seconds returns the same answer repeatedly and spends request budget you can watch draining in
requests_today. - Separate the two questions. "Is the session healthy?" and "what has it produced?" have different natural rates. Status is the cheap, frequent read; the clip list is the one that grows, and reading it on a multiple of the status interval is usually the right shape.
- Deduplicate on identity, never on count. Treat every clip read as a full snapshot and keep a set of identifiers you have already handled. Ordering is not a contract, and a list that grew from four to six does not guarantee that items five and six are the new ones.
- Do not assume anything tears itself down. Put
stop_livestreamin afinallyblock. On restart after a crash, pollcheck_livestreamwith the id you persisted before you consider opening a new session — otherwise your recovery path is a second session against the same broadcast, which nobody notices until the bill or the duplicate clips show up.
On extension: extend_livestream keeps an active session going, and the decision to call it should come from something real — the status you just read, or a human saying the broadcast is worth more coverage. Do not fire it on a blind timer, because a blind timer will happily try to extend sessions attached to broadcasts that already ended. Read the extension tool's schema and the actual shape of a check_livestream result in your own account to see what you have to reason with; this page will not invent field names for you.
What a Finished Live Clip Contains
check_clips returns finished videos, not timestamp ranges you still have to render. Each one comes back as a scored, captioned, vertical 9:16 clip with a title and a download URL.
That score is the most useful field for automation and the easiest one to over-read. It is a model's judgment of short-form potential at the moment the clip was cut — a ranking signal, not a forecast. Sort by it, review the top of the list, and resist attaching absolute meaning to any particular number.
creator_pack is the natural follow-up once you have clips worth posting — per-clip suggested titles, hooks, and best posting times for a project. And discover_trending sits on the recorded side of the product rather than this one: it finds the fastest-growing recent video in a niche, searching roughly the last three weeks of published videos, which makes it a source-finder for submit_to_clipspeed rather than a way to enumerate broadcasts that are on air right now.
publish_to_youtube is the only call that changes anything outside ClipSpeedAI. It takes a projectId, optionally a clipId, a title and a privacyStatus, and it defaults to private — a sensible default that you should think hard before overriding inside an unattended loop. Keep a human at that one point. Everything upstream is reversible; publishing is not.
Caption Style Is Chosen, Not Inferred
Captions are not a single look, and on a live session you are better off deciding before you start than re-rendering opinions afterwards. list_templates returns the caption-style templates, and the real ids are exactly these six:
karaokehormozibeastyfireyoushaeicinematic
Pass the chosen id as captionStyle. Because the ids are fixed and short, this is one of the few values on this page you can safely hard-code in a config file rather than discover at runtime — though calling list_templates once in a setup script is still the honest way to confirm the set has not grown.
Practical note for live work: caption style is a house-style decision, not a per-clip one. Pick it once for a channel, put it in the same config that holds your poll intervals, and stop thinking about it. Bikeshedding template choice mid-broadcast is time you do not have.
Saying It in English Instead
Everything above assumes you want a deterministic script. If you are working interactively inside an MCP client, you do not construct any of it — you describe the outcome, and the client selects tools and fills arguments from the schemas itself. That is the actual reason for the protocol, and if the distinction between this and a hand-written HTTP client is still fuzzy, What Is MCP? Model Context Protocol Explained is the place to start.
A live session looks like this in a terminal agent:
> Start clipping this stream while it's on air, and check on it every few minutes: https://example.com/some-live-stream > Still going. Keep the session running longer. > Show me everything we have so far with scores, best first, then close the session.
The client maps those to clip_livestream, check_livestream, extend_livestream, check_clips and stop_livestream without you naming any of them, and it resolves the identifier plumbing between subscription and project along the way. For people who want this workflow and never intend to write a line of code, MCP for Creators: Automating Video Without Code covers the same ground without the JSON.
The honest limit: an agent loop is non-deterministic. Poll intervals will be irregular, and no interactive session is going to babysit a six-hour tournament reliably. Interactive for exploration and for one-off broadcasts you are watching anyway; a script for anything scheduled, long, or unattended. Most people end up running both against the same server, which is the point of exposing the tools rather than a bespoke client.
Where This Breaks
Stated plainly, and marked where something is reasoning rather than documented behaviour.
- Expect the stream to need to be publicly reachable. A remote service can only attach to what it can fetch, so treat subscriber-gated, age-gated, geo-restricted or unlisted broadcasts as likely failures rather than assuming they work. Confirm against the error the tool actually returns before building around either answer.
- A stream that has ended is a recording. Once the broadcast is over, the recorded path —
submit_to_clipspeed— is the right tool, and it gets you the full-timeline ranking that live mode cannot offer. Inherent, not an oversight. - A quiet stream produces nothing, correctly. A session can report
monitoringfor an hour and return an empty clip list because nothing clip-worthy happened. Do not build an alert that treats "zero clips" as a fault; build one that treats "status is no longer monitoring" as a fault. - Two sessions is the classic self-inflicted wound. Restart logic that starts before it checks is how you end up paying attention to one
subscriptionIdwhile a second one runs unattended. - This is a tool server, not a versioned REST resource model. You can drive it with curl because the transport is JSON-RPC, but the contract is tool schemas that can evolve. If your architecture needs versioned resources and a formal contract, settle that question first — MCP vs REST API: When to Use Each lays out the trade.
- Compatible is not verified. A client in the compatible tier speaks the protocol. It does not mean someone drove a full six-hour live session on it and watched the clips land.
Live Now, or Just Wait for the Recording
The decision is narrower than it looks, because live clipping only wins when the timing itself is the value.
Use a native clip control when a person is already watching, the volume is a handful of clips, and the platform's own output is fine for what you are doing. The major live platforms ship some form of clip control, it costs nothing, and at that scale nothing beats it.
Edit the recording by hand when the clip carries your name and taste matters more than latency. A human editor still wins on judgment, and the recording will exist in an hour anyway.
Build your own real-time pipeline when clipping is your product, when you need control at the model level over what gets selected, or when your volume makes running the infrastructure cheaper than paying for it. Budget honestly: ingest, transcription, rendering, storage, failure handling, and someone on call when a broadcast starts at 2am.
Use a hosted live clipping API when you want clips while the broadcast is still running, you do this regularly enough that manual work stops being viable, and captioned vertical output is the deliverable rather than a starting point. ClipSpeedAI fits that when you also want the same tools available to both an agent and a cron job, and when an explicit session model with extend and stop matches how you think about a broadcast. It does not fit if you need to self-host for compliance, or if you need a contractual REST surface with an SLA. Those are real requirements and no amount of convenience substitutes for them.
One sequencing rule regardless of choice: prove clip quality on a recording before you take on session management. If the clips are not good enough on a file, they will not become good enough because you got them faster.
Planning a $1 Evaluation Around a Real Broadcast
Pricing is straightforward and worth planning around, because the evaluation window and the thing you want to evaluate are both on schedules.
One dollar opens a three-day trial — a single $1 charge today, converting to your chosen plan after three days unless you cancel. Plans are Starter at $15/month, Pro at $29/month, and Ultra at $49/month, with annual billing cutting the effective rate in half. There is no free tier. The free demo is a single run against a source video shorter than thirty minutes, which is a fine way to judge caption quality and framing on a recording, and not a way to test a live session.
So structure the trial deliberately. Three days is short, and livestreams do not start on demand. Pick a broadcaster with a predictable schedule, one you can actually catch inside the window, and plan to run one complete session end to end rather than three partial ones: open it, poll through a real monitoring stretch, exercise extend_livestream once so you have seen it work, pull clips mid-broadcast, and close with stop_livestream so you can confirm for yourself that the clips already made are still there afterward. Judge the output on your own content and your own audience, not on a reel.
Once one broadcast works end to end, chaining it into something larger is a separate exercise — scheduling, review queues, approval before anything goes public. AI Agent Video Automation: End-to-End Workflows walks complete chains of that shape, and MCP for Video Editing and Clipping Workflows covers the editing-side patterns that sit between a raw clip and something you would post.
Frequently asked questions
- Do clips really arrive during the broadcast, or does everything wait for the recording?
- During the broadcast.
clip_livestreamopens a session against a live URL and returns asubscriptionId; whilecheck_livestreamreportsmonitoring, the stream is still live and still being clipped, and finished clips can be read as they land. Every read is a correct but partial snapshot, so deduplicate on clip identity and treat the list as something that grows. - What does the status monitoring actually mean?
- It means the session is in its healthy running state: the stream is still live and clipping is happening. It is the condition your loop should continue on, and anything else is the signal to look at the full response and decide whether to extend, stop, or investigate — rather than continuing to poll blindly.
- How do I know which URLs clip_livestream will accept?
- Read its
inputSchemafrom atools/listcall rather than trusting any published example, and confirm behaviour with a real attempt. As a working assumption, expect the broadcast to need to be publicly reachable — a remote service can only attach to what it can fetch — so treat gated, unlisted or region-restricted streams as likely failures until you have seen otherwise. - If I stop a session early, do I lose the clips it already made?
- No. Clips already produced are kept when you call
stop_livestream, and they remain downloadable afterward. That is worth internalising because it removes the main reason people hesitate to close sessions cleanly: stopping costs you future clips, not past ones. - What happens if my supervisor script crashes mid-session?
- Do not assume the session tears itself down. Persist the
subscriptionIdthe moment you receive it, keepstop_livestreamin afinallyblock so the teardown runs on the exception path, and on restart pollcheck_livestreamwith the saved id before opening anything new. The failure that hurts is a recovery path that starts a second session against the same broadcast. - How often should I poll, and how do I know if I am polling too hard?
- Start at about a minute between status reads, with the clip list read on a slower multiple of that. Then measure instead of guessing:
GET /auth/api-keysreportsrate_limit,requests_todayandtotal_requestsper key, so run one full session and compare the numbers against the limit before you tighten the loop. - Can I call this from a plain script, or do I need an AI client?
- Either works. MCP over streamable HTTP is JSON-RPC 2.0 posted to a single endpoint, so curl or the official Python MCP SDK is fine — just remember to echo the
Mcp-Session-Idheader if the server issues one at initialize. Interactive clients are better for exploration; a script is better when you need a predictable cadence and a guaranteed teardown. - How is a live clip's viral score different from a recorded one's?
- Structurally it is the same field, but the conditions differ. terial than one cut five hours in, because live scoring has no access to the rest of the stream. Use it as a ranking signal within a session, review the top of the list, and do not read absolute values as performance predictions.
- Which caption styles can I use on live clips?
list_templatesreturns the caption-style templates, and the ids are exactlykaraoke,hormozi,beasty,fire,youshaeiandcinematic. Pass the one you want ascaptionStyle. Decide it once as a house style before the broadcast starts rather than per clip.- Can I have the clips published automatically as they arrive?
- You can, and you should think carefully first.
publish_to_youtubetakes aprojectId, an optionalclipId, atitleand aprivacyStatus, and it defaults to private. It is the only call that changes anything outside ClipSpeedAI, which makes it the right place to keep a human — approve, then publish. - Can I test live clipping without paying?
- Not a full session. The demo is one run against a source video under thirty minutes, which tells you about caption quality and 9:16 framing on a recording but nothing about session behaviour. A dollar opens a three-day trial that converts to your chosen plan unless cancelled — Starter $15/mo, Pro $29/mo, Ultra $49/mo, with annual billing halving the rate — so pick a broadcaster whose schedule falls inside those three days.
- What happens to my key if it leaks?
- Revoke it.
DELETE /auth/api-keys/:idsets the key inactive and stamps a revocation time, and the key list shows a prefix and name for each one so you can identify the right target. Because only the prefix is stored, a full key is visible once at creation and cannot be retrieved later — which is a good argument for issuing one named key per machine rather than sharing a single key across a laptop, a runner and a scheduler.