Bumpups API / Reference
API reference
Overview
The Bumpups API turns YouTube links into timestamped chapters and answers questions about the videos. It comes with the Pro plan and shares your minutes and chat limits with the web app. Every video you process also appears in your Workspace.
https://bumpups.com/api/v1Quick start
- Create a key on the API page of the Bumpups app and keep it on your server.
- Send a YouTube link to
POST /v1/videos. You get the video back right away with statusprocessing. - Check back at
GET /v1/videos/{id}until the status isready, then use the chapters or ask questions.
curl -X POST https://bumpups.com/api/v1/videos \
-H "Authorization: Bearer $BUMPUPS_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"url": "https://www.youtube.com/watch?v=1W4bRAKfMeM"}'
# Then check back until "status" is "ready" or "failed":
curl https://bumpups.com/api/v1/videos/VIDEO_ID -H "Authorization: Bearer $BUMPUPS_API_KEY"Authentication
Send your key in the Authorization header of every request, over HTTPS. Keys start with bu_live_. Each one is shown once, when you create it. Create up to 5, and revoke any of them from the API page: a revoked key stops working within a minute.
Authorization: Bearer bu_live_YOUR_KEYKeep keys out of web pages and apps: the API doesn't accept calls from browsers.
Videos
Process a video
POST/v1/videos
Sends a YouTube link to Bump AI. The video costs its length in whole minutes, charged once. It shows up in your Workspace too, where you can open it, chat about it and export it.
Headers
Idempotency-Keystring- Any unique string up to 255 characters. Retrying with the same key within 24 hours returns the same video and never charges again. A retry sent while the first request is still running gets 409.
Body (JSON)
urlstringrequired- A YouTube video link: watch, youtu.be, shorts, live or embed.
Videos under 30 minutes are usually ready in 1–2 minutes, longer ones in 5–15. Check back at the Location URL after the Retry-After seconds.
curl -X POST https://bumpups.com/api/v1/videos \
-H "Authorization: Bearer $BUMPUPS_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"url":"https://www.youtube.com/watch?v=kBdfcR-8hEY"}'Location: /api/v1/videos/sRV9zsGtyJRc2apg
Retry-After: 60
{
"object": "video",
"id": "sRV9zsGtyJRc2apg",
"youtube_id": "kBdfcR-8hEY",
"title": "Justice: What's The Right Thing To Do? Episode 01 \"THE MORAL SIDE OF MURDER\"",
"duration_seconds": 3296,
"minutes_charged": 54,
"status": "processing",
"chapters": null,
"chapters_text": null,
"error": null,
"app_url": "https://bumpups.com/workspace/sRV9zsGtyJRc2apg",
"created_at": "2026-10-09T20:51:39Z"
}Get a video
GET/v1/videos/{id}
The video's status and, once it's ready, its chapters, both as a list and as text ready to paste into a YouTube description.
Path parameters
idstringrequired- The id from Process a video. YouTube videos you added in the web app work too.
curl https://bumpups.com/api/v1/videos/sRV9zsGtyJRc2apg \
-H "Authorization: Bearer $BUMPUPS_API_KEY"{
"object": "video",
"id": "sRV9zsGtyJRc2apg",
"youtube_id": "kBdfcR-8hEY",
"title": "Justice: What's The Right Thing To Do? Episode 01 \"THE MORAL SIDE OF MURDER\"",
"duration_seconds": 3296,
"minutes_charged": 54,
"status": "ready",
"chapters": [
{
"start_seconds": 0,
"timestamp": "0:00",
"title": "Intro credits and course framing"
},
{
"start_seconds": 150,
"timestamp": "2:30",
"title": "Audience poll: trolley dilemma choices"
},
{
"start_seconds": 327,
"timestamp": "5:27",
"title": "Bridge variant: would you push the fat man?"
}
],
"chapters_text": "0:00 - Intro credits and course framing\n2:30 - Audience poll: trolley dilemma choices\n5:27 - Bridge variant: would you push the fat man?",
"error": null,
"app_url": "https://bumpups.com/workspace/sRV9zsGtyJRc2apg",
"created_at": "2026-10-09T20:51:39Z"
}Trimmed to the first 3 of 15 chapters.
Questions
Ask a question
POST/v1/videos/{id}/questions
Asks Bump AI about a ready video. Questions don't use minutes. Each video allows 25, counted together with web chat, and one is answered at a time. Answers appear in a chat named “API” on the video, and later questions keep the context.
Path parameters
idstringrequired- The video's id.
Body (JSON)
questionstringrequired- Up to 2,000 characters.
curl -X POST https://bumpups.com/api/v1/videos/sRV9zsGtyJRc2apg/questions \
-H "Authorization: Bearer $BUMPUPS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"question":"Which cases does the professor use to test our moral intuitions?"}'Location: /api/v1/videos/sRV9zsGtyJRc2apg/questions/kEV7Adv4Ed0RyJfI
Retry-After: 10
{
"object": "question",
"id": "kEV7Adv4Ed0RyJfI",
"video_id": "sRV9zsGtyJRc2apg",
"question": "Which cases does the professor use to test our moral intuitions?",
"created_at": "2026-10-09T21:37:33Z",
"status": "pending",
"answer": null,
"error": null
}Get an answer
GET/v1/videos/{id}/questions/{question_id}
The question's status and, once answered, the answer in Markdown, the same answer Bump AI gives in chat.
Path parameters
idstringrequired- The video's id.
question_idstringrequired- The id from Ask a question.
curl https://bumpups.com/api/v1/videos/sRV9zsGtyJRc2apg/questions/kEV7Adv4Ed0RyJfI \
-H "Authorization: Bearer $BUMPUPS_API_KEY"{
"object": "question",
"id": "kEV7Adv4Ed0RyJfI",
"video_id": "sRV9zsGtyJRc2apg",
"question": "Which cases does the professor use to test our moral intuitions?",
"created_at": "2026-10-09T21:37:33Z",
"status": "answered",
"answer": "The professor presents five main cases to test moral intuitions:\n\n* **The trolley car driver:** You are driving a runaway trolley and must choose between staying on the track to kill five workers or turning onto a side track to kill one.\n* **The onlooker on the bridge:** You are watching a runaway trolley and can save five workers on the track by pushing a heavy man off a bridge to stop the trolley, killing him.\n* **The transplant surgeon:** You have five patients who will die without organ transplants. You can save them by killing a healthy patient who came in for a checkup and harvesting his organs.",
"error": null
}Trimmed to the first 3 of 5 cases.
Account
Get your minutes
GET/v1/account
Your plan, the minutes you have left (the same balance as the web app) and when they reset.
curl https://bumpups.com/api/v1/account \
-H "Authorization: Bearer $BUMPUPS_API_KEY"{
"object": "account",
"plan": "pro",
"minutes_limit": 1000,
"minutes_used": 67,
"minutes_left": 933,
"resets_at": "2026-11-01T00:00:00Z"
}The video object
Fields
idstring- The video's id, also used in its Workspace link.
statusstring- processing, ready or failed.
youtube_idstring- The YouTube video id.
titlestring- The YouTube title.
duration_secondsinteger- The video's length.
minutes_chargedinteger- Minutes used. 0 when processing failed, because the minutes were refunded.
chaptersarray | null- Once ready: { start_seconds, timestamp, title } for each chapter.
chapters_textstring | null- Once ready: the chapters as lines like 0:00 - Intro, for a YouTube description.
errorobject | null- When failed: { code, message }.
app_urlstring- The video in the Bumpups web app.
created_atstring- When it was added (RFC 3339, UTC).
The question object
Fields
idstring- The question's id.
video_idstring- The video it's about.
statusstring- pending, answered or failed.
questionstring- What you asked.
answerstring | null- Once answered: Markdown, citing moments as m:ss.
errorobject | null- When failed: { code, message }. Failed questions aren't counted.
created_atstring- When it was asked (RFC 3339, UTC).
Errors
Errors use the RFC 9457 problem format (application/problem+json). Branch on code, show detail to people, and quote request_id (also in the X-Request-Id header) if you contact support.
{
"type": "https://bumpups.com/api/docs#not_enough_minutes",
"title": "Not enough minutes",
"status": 402,
"detail": "This video needs 54 minutes and you have 17 left this cycle.",
"code": "not_enough_minutes",
"request_id": "req_8fK2mQ7xLp3aB9cD0eF1",
"minutes_needed": 54,
"minutes_left": 17
}invalid_requestinvalid_url
A field is missing, unknown or the wrong type, or the link isn't a YouTube video.
invalid_api_key
The key is missing, wrong or revoked.
not_enough_minutes
The video needs more minutes than you have left. See minutes_needed and minutes_left.
pro_required
The account isn't on Pro. Keys start working again after an upgrade.
not_found
No such endpoint, or no such video or question in your account.
method_not_allowed
Use the method in the Allow header.
video_not_readyquestion_in_progressidempotency_key_in_use
Wait until the video is ready, until the last answer arrives, or until the first request with this Idempotency-Key finishes. Retry-After says how long.
payload_too_large
Request bodies can be up to 16 KB.
unsupported_media_type
Send JSON with Content-Type: application/json.
video_not_supportedidempotency_key_reused
The video is private, live, over 3 hours, or unlisted and under 30 minutes (see reason), or the Idempotency-Key was already used for another video.
question_limit_reached
The video has used its 25 questions (web chat and API together), or it already has 7 chats.
internal_error
Something failed on our side. Retry, and quote the request_id if it keeps happening.
unavailable
Maintenance, or YouTube didn't answer. Retry after the Retry-After seconds.
Limits
- Plan
- Pro. Keys stop working while an account is on Free and start again after an upgrade.
- Minutes
- A video costs its length in whole minutes (at least 1), from the same balance as the web app. No chapters, no charge.
- Questions
- 25 per video, counted together with web chat, one at a time. They don't use minutes.
- Videos
- Public YouTube videos up to 3 hours. Unlisted videos need to be 30 minutes or longer. Live streams and premieres aren't supported.
- Keys
- Up to 5 per account. Revoked keys stop working within a minute.
- Requests
- JSON bodies up to 16 KB. Keys are for servers: browsers can't call the API.
Versioning
The version is in the path. New fields, endpoints and enum values can appear in v1 at any time, so ignore what you don't recognize. A breaking change would come as /v2, with the old version kept running for at least 12 months.