Timeless
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.
API Reference
For full endpoint documentation with response schemas, status enums, and detailed examples, read api-reference.md (in this skill folder).
Prerequisites
TIMELESS_ACCESS_TOKENenv var (get token at my.timeless.day/api-token)yt-dlpfor YouTube downloads (install via package manager:apt install yt-dlp,brew install yt-dlp, orpip install yt-dlp. Alternatively setYTDLP_PATHto point to an existing binary.)
Set up in OpenClaw:
openclaw config patch env.vars.TIMELESS_ACCESS_TOKEN=<your_token>
Base URL
https://my.timeless.day
Authentication Header
All requests:
Authorization: Token $TIMELESS_ACCESS_TOKEN
Operations
1. List Meetings
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=ownedandinclude=shared, then merge.
2. List Rooms
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 }] }
3. Get Space (Meeting or Room Details)
Spaces have three access levels. Try in order until one succeeds:
3a. Private Space (your own)
curl -s "https://my.timeless.day/api/v1/spaces/{uuid}/" \
-H "Authorization: Token $TIMELESS_ACCESS_TOKEN"
3b. Workspace Space (shared within team)
host_uuidis required for shared spaces. Get it from thehost_user.uuidfield 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"
3c. Public Space (publicly shared)
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 hasuuid,name,start_ts,end_ts,status,language)artifacts[]: AI-generated documents. Checktypefield (e.g.,"summary"). Content is incontent.body(HTML).contacts[]: Each has nestedconversations[]organizations[]: Each has nestedconversations[]threads[]: AI chat threads. Usethreads[0].uuidto chat with the agent.
Collecting all conversations in a room:
Deduplicate conversation UUIDs from conversations[] + contacts[].conversations[] + organizations[].conversations[].
4. Get Transcript
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:
- From List Meetings:
primary_conversation_uuidfield - From Get Space:
conversations[].uuid
Format as readable text by mapping speaker_id to speaker names:
[00:00:00] Alice Johnson: ...
[00:00:03] Bob Smith: ...
5. Get Recording URL
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.
6. Upload a Recording
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
7. Resolve a Timeless Share URL
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).
8. Chat with Timeless AI
Ask questions about a meeting or room.
Step 1: Send Message
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).
Step 2: Poll for Response
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.
9. Create a Room
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.
10. Add/Remove Conversations from a Room
# 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).
Common Workflows
Export All Transcripts
- List all meetings with
include=owned&status=COMPLETED&per_page=100 - Paginate through all pages
- For each meeting, fetch transcript using
primary_conversation_uuid
Get Everything from a Room
- Get Space for the room UUID
- Collect all conversation UUIDs from
conversations[],contacts[].conversations[],organizations[].conversations[](deduplicate) - Fetch transcript for each conversation UUID
Search and Read
- List meetings with
search=your+query - Pick the meeting, get its
primary_conversation_uuid - Fetch transcript
- Optionally, Get Space for AI summaries in
artifacts[]
Automation Patterns
Timeless does not have webhooks yet. To build automations that react to new meetings, use cron polling with a state file.
The Pattern: Poll, Deduplicate, Act
A cron job runs every 5-10 minutes. Each run:
- Read a state file (
timeless-processed.json). Create it with an emptyprocessedarray if missing. - Poll for completed meetings:
GET /api/v1/spaces/meeting/?include=owned&status=COMPLETED&start_date=YYYY-MM-DD - For each meeting: if its
uuidis already inprocessed, skip it. - For new meetings: fetch whatever data you need (transcript, space details, artifacts), then run your automation logic.
- Append processed UUIDs to the state file.
- If nothing is new, exit silently. Do not message the user.
State file format:
{
"processed": ["uuid-1", "uuid-2", "uuid-3"],
"last_check": "2026-03-05T12:00:00Z"
}
Key rules:
- A UUID in
processedis never processed again. This prevents duplicate work. - Periodically prune old UUIDs (e.g., older than 30 days) to keep the file small.
- Also fetch
include=sharedif 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."
What You Can Do With a New Meeting
Once the polling pattern detects a new completed meeting, you have access to:
- Transcript (full speaker-attributed text via Get Transcript)
- AI summary and action items (via Get Space
artifacts[]) - Participants and metadata (via Get Space
conversations[].event.attendees) - Recording URL (via Get Recording)
- AI chat (ask follow-up questions via Chat with Timeless AI)
Combine these with any external tool or API. Some examples of what people build:
- Auto-generate a recap presentation or document after every meeting
- Feed meeting data into a dashboard that tracks topics, action items, or meeting load over time
- Auto-curate Timeless rooms by adding conversations that match rules (participant, title, topic)
- Push summaries or action items to Slack, email, Notion, or a CRM
- Run sentiment analysis or extract custom fields from transcripts
- Build a searchable meeting knowledge base
The pattern is always the same: poll for new meetings, pull the data, do your thing.
Capture: Podcasts
Scripts in scripts/ folder.
- Search:
bash scripts/podcast.sh search "podcast name" - List episodes:
bash scripts/podcast.sh episodes FEED_URL [limit] - Download:
bash scripts/podcast.sh download MP3_URL /tmp/episode.mp3 - Upload to Timeless:
bash scripts/upload.sh /tmp/episode.mp3 en "Episode Title" - Clean up the file from /tmp
Spotify links
Extract the episode title via oEmbed, then search by name:
curl -s "https://open.spotify.com/oembed?url=SPOTIFY_URL"
Capture: YouTube
- Get info:
bash scripts/youtube.sh info "YOUTUBE_URL" - Download video:
bash scripts/youtube.sh download "YOUTUBE_URL" /tmp/video.mp4 - Upload to Timeless:
bash scripts/upload.sh /tmp/video.mp4 en "Video Title" - Clean up the file from /tmp
Downloads as mp4 (video+audio). No ffmpeg needed. Uses the best pre-muxed format (typically 720p), which is fine for Timeless.
Capture: Adding to a Room
After uploading, attach the content to a Timeless room for organized collections.
- Upload returns a
space_uuid. PollGET /api/v1/spaces/{space_uuid}/untilis_processing=false. - From the space response, get the
conversation.uuid. - Add to room:
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"}
Notes
- Podcast MP3s can be large (100-300MB for long episodes). Downloads may take a minute.
- YouTube downloads require yt-dlp. If not installed, the script will fail with a clear error.
- Always clean up downloaded files from /tmp after uploading.
- Set
YTDLP_PATHenv var if yt-dlp is not on PATH.
Error Handling
| 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. |
Rate Limiting
No official limits, but be respectful:
- 0.5s delay between sequential requests
- Max ~60 requests per minute
- Use pagination, don't fetch everything at once