> Source: github.com/supertools/timeless-skills
Interact with Timeless meeting data: search meetings, read transcripts, get AI summaries, browse rooms, upload recordings, chat with the AI agent, and capture podcasts/YouTube videos for transcription.
For full endpoint documentation with response schemas, status enums, and detailed examples, read api-reference.md (in this skill folder).
TIMELESS_ACCESS_TOKEN env var (get token at my.timeless.day/api-token)yt-dlp for YouTube downloads (install via package manager: apt install yt-dlp, brew install yt-dlp, or pip install yt-dlp. Alternatively set YTDLP_PATH to point to an existing binary.)Set up in OpenClaw:
openclaw config patch env.vars.TIMELESS_ACCESS_TOKEN=<your_token>
https://my.timeless.day
All requests:
Authorization: Token $TIMELESS_ACCESS_TOKEN
GET /api/v1/spaces/meeting/
Required parameter: include must be owned or shared.
| Parameter | Type | Description |
|---|---|---|
| ----------- | ------ | ------------- |
include | string | Required. owned or shared |
search | string | Search by title or attendees |
start_date | string | From date (YYYY-MM-DD) |
end_date | string | To date (YYYY-MM-DD) |
status | string | COMPLETED, SCHEDULED, PROCESSING, FAILED |
page | integer | Page number (default: 1) |
per_page | integer | Results per page (default: 20) |
curl -s "https://my.timeless.day/api/v1/spaces/meeting/?include=owned&status=COMPLETED&per_page=50" \
-H "Authorization: Token $TIMELESS_ACCESS_TOKEN"
Response: { count, next, previous, results: [{ uuid, title, start_ts, end_ts, status, primary_conversation_uuid, host_user, conversation_source, created_at }] }
Key fields:
uuid = space UUID (for Get Space)primary_conversation_uuid = conversation UUID (for Get Transcript)> To get ALL meetings, make two calls: include=owned and include=shared, then merge.
GET /api/v1/spaces/room/
Same query parameters as List Meetings (except rooms don't have start_ts, end_ts, or status).
curl -s "https://my.timeless.day/api/v1/spaces/room/?include=owned" \
-H "Authorization: Token $TIMELESS_ACCESS_TOKEN"
Response: { count, next, previous, results: [{ uuid, title, host_user, created_at }] }
Spaces have three access levels. Try in order until one succeeds:
curl -s "https://my.timeless.day/api/v1/spaces/{uuid}/" \
-H "Authorization: Token $TIMELESS_ACCESS_TOKEN"
> host_uuid is required for shared spaces. Get it from the host_user.uuid field in the List Meetings or List Rooms response.
curl -s "https://my.timeless.day/api/v1/spaces/{uuid}/workspace/?host_uuid={hostUuid}" \
-H "Authorization: Token $TIMELESS_ACCESS_TOKEN"
curl -s "https://my.timeless.day/api/v1/spaces/public/{uuid}/{hostUuid}/" \
-H "Authorization: Token $TIMELESS_ACCESS_TOKEN"
Response includes:
conversations[]: Recordings in this space (each has uuid, name, start_ts, end_ts, status, language)artifacts[]: AI-generated documents. Check type field (e.g., "summary"). Content is in content.body (HTML).contacts[]: Each has nested conversations[]organizations[]: Each has nested conversations[]threads[]: AI chat threads. Use threads[0].uuid to chat with the agent.Collecting all conversations in a room:
Deduplicate conversation UUIDs from conversations[] + contacts[].conversations[] + organizations[].conversations[].
curl -s "https://my.timeless.day/api/v1/conversation/{conversation_uuid}/transcript/" \
-H "Authorization: Token $TIMELESS_ACCESS_TOKEN"
Response:
{
"items": [
{ "text": "...", "start_time": 0.5, "end_time": 3.2, "speaker_id": "speaker_0" }
],
"speakers": [
{ "id": "speaker_0", "name": "Alice Johnson" }
],
"language": "he"
}
How to get conversation_uuid:
primary_conversation_uuid fieldconversations[].uuidFormat as readable text by mapping speaker_id to speaker names:
[00:00:00] Alice Johnson: ...
[00:00:03] Bob Smith: ...
curl -s "https://my.timeless.day/api/v1/conversation/{conversation_uuid}/recording/" \
-H "Authorization: Token $TIMELESS_ACCESS_TOKEN"
Response: { "media_url": "https://storage.googleapis.com/...signed..." }
> The URL is time-limited. Fetch it fresh when needed.
Three-step flow:
# Step 1: Get presigned URL
curl -X POST "https://my.timeless.day/api/v1/conversation/storage/presigned-url/" \
-H "Authorization: Token $TIMELESS_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"file_name": "recording.mp3", "file_type": "audio/mpeg"}'
# Step 2: Upload file to the presigned URL
curl -X PUT "PRESIGNED_URL" \
-H "Content-Type: audio/mpeg" \
--upload-file recording.mp3
# Step 3: Trigger processing
curl -X POST "https://my.timeless.day/api/v1/conversation/process/media/" \
-H "Authorization: Token $TIMELESS_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"language": "he", "filename": "Recording Title"}'
Response (step 3): { "event_uuid": "...", "space_uuid": "..." }
Poll GET /api/v1/spaces/{space_uuid}/ until is_processing is false.
Or use the helper script: bash scripts/upload.sh FILE_PATH LANGUAGE [TITLE]
Supported formats: mp3, wav, m4a, mp4, webm, ogg
URLs like https://my.timeless.day/m/ENCODED_ID contain two Base64-encoded short IDs (22 chars each).
Decoding (shell):
ENCODED="the_part_after_/m/"
DECODED=$(echo "$ENCODED" | base64 -d)
SPACE_ID=$(echo "$DECODED" | cut -c1-22)
HOST_ID=$(echo "$DECODED" | cut -c23-44)
Decoding (Python):
import base64
def decode_timeless_url(url):
encoded = url.rstrip('/').split('/m/')[-1]
combined = base64.b64decode(encoded).decode()
return combined[:22], combined[22:] # (space_id, host_id)
After decoding, fetch with Get Space (try private -> workspace -> public).
Ask questions about a meeting or room.
curl -X POST "https://my.timeless.day/api/v1/agent/space/chat/" \
-H "Authorization: Token $TIMELESS_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"space_uuid": "SPACE_UUID",
"thread_uuid": "THREAD_UUID",
"message": {
"role": "user",
"parts": [{"type": "text", "text": "What were the action items?"}],
"date": "'$(date -u +%Y-%m-%dT%H:%M:%S.000Z)'",
"metadata": {"timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%S.000Z)'", "mentions": []},
"id": "'$(cat /proc/sys/kernel/random/uuid 2>/dev/null || uuidgen)'"
}
}'
Get thread_uuid from the space's threads[0].uuid (via Get Space).
curl -s "https://my.timeless.day/api/v1/agent/threads/{thread_uuid}/" \
-H "Authorization: Token $TIMELESS_ACCESS_TOKEN"
Poll every 2-3 seconds until is_running is false. The AI response is the last message with role: "assistant" in the messages array.
curl -X POST "https://my.timeless.day/api/v1/spaces/" \
-H "Authorization: Token $TIMELESS_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"has_onboarded": true, "space_type": "ROOM", "title": "My Room"}'
Response: Full space object. Extract uuid for adding resources.
# Add a conversation
curl -X POST "https://my.timeless.day/api/v1/spaces/{room_uuid}/resources/" \
-H "Authorization: Token $TIMELESS_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"resource_type": "CONVERSATION", "resource_uuid": "CONVERSATION_UUID"}'
# Remove a conversation
curl -X DELETE "https://my.timeless.day/api/v1/spaces/{room_uuid}/resources/" \
-H "Authorization: Token $TIMELESS_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"resource_type": "CONVERSATION", "resource_uuid": "CONVERSATION_UUID"}'
Call Add once per conversation you want to attach. Get conversation UUIDs from List Meetings (primary_conversation_uuid) or Get Space (conversations[].uuid).
include=owned&status=COMPLETED&per_page=100primary_conversation_uuidconversations[], contacts[].conversations[], organizations[].conversations[] (deduplicate)search=your+queryprimary_conversation_uuidartifacts[]Timeless does not have webhooks yet. To build automations that react to new meetings, use cron polling with a state file.
A cron job runs every 5-10 minutes. Each run:
timeless-processed.json). Create it with an empty processed array if missing.GET /api/v1/spaces/meeting/?include=owned&status=COMPLETED&start_date=YYYY-MM-DDuuid is already in processed, skip it.State file format:
{
"processed": ["uuid-1", "uuid-2", "uuid-3"],
"last_check": "2026-03-05T12:00:00Z"
}
Key rules:
processed is never processed again. This prevents duplicate work.include=shared if the automation should cover meetings shared with you.Cron setup (OpenClaw):
openclaw cron add "timeless-poll" --schedule "*/5 * * * *" --task "Check for new completed Timeless meetings. Read timeless-processed.json for state. Poll the API. For new meetings: [your automation here]. If nothing new, reply HEARTBEAT_OK."
Once the polling pattern detects a new completed meeting, you have access to:
artifacts[])conversations[].event.attendees)Combine these with any external tool or API. Some examples of what people build:
The pattern is always the same: poll for new meetings, pull the data, do your thing.
Scripts in scripts/ folder.
bash scripts/podcast.sh search "podcast name"bash scripts/podcast.sh episodes FEED_URL [limit]bash scripts/podcast.sh download MP3_URL /tmp/episode.mp3bash scripts/upload.sh /tmp/episode.mp3 en "Episode Title"Extract the episode title via oEmbed, then search by name:
curl -s "https://open.spotify.com/oembed?url=SPOTIFY_URL"
bash scripts/youtube.sh info "YOUTUBE_URL"bash scripts/youtube.sh download "YOUTUBE_URL" /tmp/video.mp4bash scripts/upload.sh /tmp/video.mp4 en "Video Title"Downloads as mp4 (video+audio). No ffmpeg needed. Uses the best pre-muxed format (typically 720p), which is fine for Timeless.
After uploading, attach the content to a Timeless room for organized collections.
space_uuid. Poll GET /api/v1/spaces/{space_uuid}/ until is_processing=false.conversation.uuid.POST /api/v1/spaces/{room_uuid}/resources/ with {"resource_type": "CONVERSATION", "resource_uuid": "CONV_UUID"}To create a new room first: POST /api/v1/spaces/ with {"has_onboarded": true, "space_type": "ROOM", "title": "My Collection"}
YTDLP_PATH env var if yt-dlp is not on PATH.| Code | Action |
|---|---|
| ------ | -------- |
| 401 | Token expired. Re-authenticate at my.timeless.day/api-token |
| 403 | No access. Try workspace or public endpoint. |
| 404 | Not found. Check UUID. |
| 429 | Rate limited. Wait and retry. |
No official limits, but be respectful:
共 1 个版本