VibesAI-api 1.3.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,28 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 vibes-api contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ---
24
+
25
+ This project is NOT affiliated with, endorsed by, or officially supported by
26
+ Meta Platforms, Inc. or Vibes. "Vibes" and "Meta" are trademarks of their
27
+ respective owners. Use of this software is at your own risk; respect the
28
+ Vibes Terms of Service at https://vibes.ai/.
@@ -0,0 +1,600 @@
1
+ Metadata-Version: 2.4
2
+ Name: VibesAI-api
3
+ Version: 1.3.2
4
+ Summary: Unofficial Python API client for vibes.ai
5
+ Author-email: Ashiq Hussain Mir <imsrenpsycho@gmail.com>
6
+ License: MIT
7
+ Requires-Python: >=3.8
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: requests>=2.28.0
11
+ Provides-Extra: server
12
+ Requires-Dist: fastapi>=0.104.0; extra == "server"
13
+ Requires-Dist: uvicorn[standard]>=0.24.0; extra == "server"
14
+ Requires-Dist: pydantic>=2.0.0; extra == "server"
15
+ Requires-Dist: Pillow>=10.0.0; extra == "server"
16
+ Provides-Extra: dev
17
+ Requires-Dist: pytest>=7.0; extra == "dev"
18
+ Dynamic: license-file
19
+
20
+ # vibes-api
21
+
22
+ > **Unofficial** Python API client for [vibes.ai](https://vibes.ai/) — Meta's AI video creation studio. Generate videos, images, TTS, lip-sync, and more, all from a Python script or CLI.
23
+
24
+ This package was built by reverse-engineering the vibes.ai Next.js bundles and observing real network traffic. It is **not** affiliated with, endorsed by, or officially supported by Meta or Vibes.
25
+
26
+ ---
27
+
28
+ ## ⚡ Quick start
29
+
30
+ ```bash
31
+ # 1) Install
32
+ pip install -e /home/z/my-project/download/vibes-api
33
+
34
+ # 2) Set your cookie (grab from DevTools → Application → Cookies → vibes.ai)
35
+ export VIBES_META_SESSION="e60e910a-242a-...-K54E"
36
+
37
+ # 3) Generate your first video
38
+ vibes-api one-shot \
39
+ --prompt "A serene mountain landscape at sunset" \
40
+ --aspect-ratio 16:9 --resolution 720p --variations 4 \
41
+ --download-dir ./out
42
+ ```
43
+
44
+ Or in Python:
45
+
46
+ ```python
47
+ from vibes_api import VibesClient, AspectRatio, Resolution
48
+
49
+ client = VibesClient(meta_session="...")
50
+ project = client.create_project(name="My Video")
51
+ batch = client.generate_video(
52
+ project_id=project["id"],
53
+ prompt="A serene mountain landscape at sunset",
54
+ aspect_ratio=AspectRatio.LANDSCAPE,
55
+ resolution=Resolution.P720,
56
+ variations=4,
57
+ )
58
+ client.download_video(batch["content"][0]["id"], "sunset.mp4")
59
+ ```
60
+
61
+ ---
62
+
63
+ ## 📦 What's inside
64
+
65
+ ### Core capabilities (v1.1.0)
66
+
67
+ | Feature | Method | Notes |
68
+ |---|---|---|
69
+ | **Auth** | `get_me()`, `get_system_status()`, `logout()` | Cookie-based |
70
+ | **Projects** | `list_projects()`, `create_project()`, `get_project()`, `update_project()`, `delete_project()`, `duplicate_project()` | |
71
+ | **Video generation (t2v)** | `generate_video()` | text-to-video, 1-4 variations |
72
+ | **Image generation (t2i)** | `generate_image()` | synchronous, returns immediately |
73
+ | **🎥 Video extend (auto)** | `auto_extend_video()`, `extend_video(prompt=None)` | extends a video by ~5s, no directive |
74
+ | **🎥 Video extend (manual)** | `manual_extend_video()`, `extend_video(prompt=...)` | extends with a directive prompt |
75
+ | **🎥 Video edit (v2v)** | `edit_video()` | re-render existing video with a directive |
76
+ | **🎥 Image animate (auto)** | `auto_animate_image()` | animate a still image with original prompt |
77
+ | **🎥 Image animate (manual)** | `manual_animate_image()` | animate with a directive prompt |
78
+ | **🔄 Regenerate batch** | `regenerate_batch()` | re-roll with same or new prompt |
79
+ | **🖼️ Image editing** | `edit_image()` | prompt-driven edits |
80
+ | **✨ Prompt enhancement** | `enhance_prompt()` | returns 4 AI-rewritten variations |
81
+ | **🗣️ Lip sync** | `generate_lipsync()` | image + audio + script → video |
82
+ | **🔊 TTS** | `tts()`, `list_voices()`, `save_tts_audio()` | 41 preset voices |
83
+ | **🎭 Start/end frame** | `generate_video(start_frame=..., end_frame=...)`, `build_frame_handle()` | image-to-video with keyframes |
84
+ | **🧙 Ingredients (character/style/scene)** | `list_characters()`, `list_styles()`, `list_scenes()`, `create_ingredient()`, `delete_ingredient()` | studio ingredient CRUD |
85
+ | **🧙 Ingredient refs in generation** | `ingredients=[...]`, `create_ingredients=[...]` | apply or inline-create |
86
+ | **🎨 Moodboards** | `list_moodboards()`, `get_moodboard()`, `create_moodboard()`, `delete_moodboard()` | |
87
+ | **⬆️ Uploads** | `upload_image()`, `upload_image_file()`, `upload_video_direct()`, `upload_audio_direct()`, `upload_media()`, `upload_profile_picture()` | |
88
+ | **📚 Media library** | `list_media()`, `favorite_content_item()`, `delete_content_item()`, `delete_content_items()` | |
89
+ | **⬇️ Download** | `download_video()`, `download_image()` | |
90
+ | **🔗 Share links** | `create_share_link()`, `list_share_links()`, `revoke_share_link()` | |
91
+ | **🎵 Music library** | `search_music()`, `lookup_music_thumbnail()`, `clip_music()`, `clip_audio()` | |
92
+ | **💬 Timeline chat** | `timeline_chat()` | streaming AI assistant (SSE) |
93
+ | **🎬 Timeline export** | `export_timeline()`, `export_timeline_async()`, `check_export_status()`, `cancel_export()` | render composition → MP4 |
94
+ | **🔄 Real-time sync** | `get_sync_status()`, `stream_sync_updates()`, `stream_batch_updates()` | SSE for collaborative editing |
95
+ | **📊 Quota** | `get_quota_upsell()` | |
96
+ | **⚙️ Account settings** | `delete_account()`, `delete_all_media()`, `remove_all_posts()` | |
97
+ | **🐛 Bug reports** | `report_bug()`, `record_consent()` | |
98
+ | **🤝 Collaborators** | `list_collaborators()`, `remove_collaborator()` | |
99
+ | **📦 Project assets** | `list_project_assets()`, `add_project_asset()`, `import_project_assets()`, `list_available_assets()` | cross-project reuse |
100
+ | **⏳ Batch polling** | `poll_batch()`, `list_batches()`, `list_project_batches()`, `get_batch()`, `delete_batch()` | |
101
+ | **🚀 One-shot** | `create_video_from_prompt()` | end-to-end convenience |
102
+
103
+ ### CLI
104
+
105
+ The `vibes-api` CLI exposes every feature as a subcommand. Run `vibes-api --help` for the full list.
106
+
107
+ ```bash
108
+ # User
109
+ vibes-api me
110
+
111
+ # Projects
112
+ vibes-api projects list
113
+ vibes-api projects create --name "My Video"
114
+ vibes-api projects get <id>
115
+ vibes-api projects delete <id> --delete-assets
116
+
117
+ # Video generation
118
+ vibes-api videos generate --project-id <id> --prompt "sunset over ocean" \
119
+ --aspect-ratio 16:9 --resolution 720p --variations 4 --download-dir ./out
120
+
121
+ # 🆕 Video extend (auto/manual)
122
+ vibes-api videos extend --project-id <id> --batch-id <batch> \
123
+ --content-id <content> # auto-extend (no --prompt)
124
+ vibes-api videos extend --project-id <id> --batch-id <batch> \
125
+ --prompt "camera pans up to reveal the sky" # manual extend
126
+
127
+ # 🆕 Video edit (v2v)
128
+ vibes-api videos edit --project-id <id> --batch-id <batch> \
129
+ --prompt "change the weather to rain"
130
+
131
+ # Image generation
132
+ vibes-api images generate --project-id <id> --prompt "cyberpunk city"
133
+
134
+ # 🆕 Image animate (auto/manual)
135
+ vibes-api images animate --project-id <id> --content-id <content>
136
+ vibes-api images animate --project-id <id> --content-id <content> \
137
+ --prompt "camera zooms in slowly"
138
+
139
+ # 🆕 Batch regenerate (re-roll)
140
+ vibes-api batches regenerate <batch-id> --project-id <id>
141
+ vibes-api batches regenerate <batch-id> --project-id <id> --prompt "new prompt"
142
+
143
+ # 🆕 Ingredient CRUD
144
+ vibes-api ingredients list [--type CHARACTER|STYLE|SETTING]
145
+ vibes-api ingredients create --name "My Character" --type CHARACTER \
146
+ --image-ent-id <id> --image-url <url>
147
+ vibes-api ingredients delete <ingredient_id>
148
+
149
+ # TTS
150
+ vibes-api voices list
151
+ vibes-api tts --voice play_ai_Marisol --text "Hello world" --out hello.mp3
152
+
153
+ # Media library
154
+ vibes-api media list --type video --limit 10
155
+ vibes-api media download --id <id> --out video.mp4
156
+ vibes-api media delete --ids <id1> <id2>
157
+
158
+ # Prompt enhancement
159
+ vibes-api prompts enhance --prompt "a cat"
160
+
161
+ # Share links
162
+ vibes-api share create --entity-type project --entity-id <id>
163
+ vibes-api share list --entity-type project --entity-id <id>
164
+ vibes-api share revoke <share_link_id>
165
+
166
+ # Batches
167
+ vibes-api batches list --project-id <id>
168
+ vibes-api batches get <batch_id>
169
+ vibes-api batches poll <batch_id> --timeout 180
170
+
171
+ # Music
172
+ vibes-api music search --query "lofi"
173
+
174
+ # Timeline AI chat
175
+ vibes-api chat "add a 5 second sunset clip"
176
+
177
+ # 🆕 Real-time sync
178
+ vibes-api sync status --entity-type project --entity-id <id>
179
+ vibes-api sync stream --entity-type project --entity-id <id> # Ctrl+C to stop
180
+
181
+ # 🆕 Quota
182
+ vibes-api quota
183
+
184
+ # End-to-end one-shot
185
+ vibes-api one-shot --prompt "sunset over ocean" --download-dir ./out
186
+ ```
187
+
188
+ ---
189
+
190
+ ## 🎬 Generation flow (under the hood)
191
+
192
+ Vibes uses a **two-step generation pattern**:
193
+
194
+ ```
195
+ 1) POST /api/generation-batches → create a batch shell (with client-generated UUID v7)
196
+ 2) POST /api/generate/videos → trigger actual generation
197
+ 3) GET /api/generation-batches/{id} → poll until isComplete=true
198
+ OR /api/generation-batches/{id}/stream (SSE)
199
+ ```
200
+
201
+ The client abstracts this away behind `generate_video()` (which polls by default) and `generate_image()` (which is synchronous).
202
+
203
+ ### Batch IDs are UUID v7 with `batch-` prefix
204
+
205
+ The server expects batch IDs to be **UUID v7** (timestamp-ordered) prefixed with `batch-` so it can derive the creation time from the high bits AND so that the download endpoint accepts the content IDs. The client generates these internally via `_uuid_v7()`. Special flows use different prefixes:
206
+ - `batch-<uuid_v7>` — normal text/image generation
207
+ - `extend-<timestamp>-<random>` — video extension
208
+ - `image2video-<timestamp>-<random>` — image-to-video (animate)
209
+ - `video2video-<timestamp>-<random>` — video-to-video (edit)
210
+
211
+ ### Aspect ratios & resolutions
212
+
213
+ Only **3 aspect ratios** are supported (verified live):
214
+
215
+ | Aspect | Image dimensions | Notes |
216
+ |---|---|---|
217
+ | `1:1` | 1280×1280 | Square |
218
+ | `9:16` | 720×1280 | Portrait (UI default) |
219
+ | `16:9` | 1280×720 | Landscape |
220
+
221
+ Resolutions: `480p` (default, faster) and `720p` (slower but higher quality).
222
+
223
+ ### Models
224
+
225
+ | Type | Default model | Description |
226
+ |---|---|---|
227
+ | Image | `midjen-base` | Standard image generation |
228
+ | Video (t2v / i2v) | `midjen-short` | ~5 second clips |
229
+ | **Video extend** | `midjen-extend` | For extending an existing video |
230
+ | **Video edit (v2v)** | `midjen-video-edit` | For re-rendering with a directive |
231
+ | Lip sync | `lipsync` / `midjen-lipsync-async` | Lip-sync generation |
232
+ | Prompt LLM | `gemini-2.5-flash` | Used for prompt enhancement |
233
+
234
+ ### Generation types
235
+
236
+ | `generationType` | When to use |
237
+ |---|---|
238
+ | `t2v` | text → video |
239
+ | `t2i` | text → image |
240
+ | `i2v` | image (start frame) → video |
241
+ | `extend` | extend an existing video |
242
+ | `v2v` | video → video (re-render with directive) |
243
+ | `lipsync` | lip-sync generation |
244
+
245
+ ---
246
+
247
+ ## 🎭 Ingredients (characters, styles, scenes)
248
+
249
+ Vibes supports three ingredient types:
250
+ - **CHARACTER** (UI: "Character") — applies via `orefImageHandle` internally
251
+ - **STYLE** (UI: "Style") — applies via `srefImageHandle` internally
252
+ - **SETTING** (UI: "Scene") — applies via `settingImageHandles` internally
253
+
254
+ There are three ways to reference an ingredient in a generation:
255
+
256
+ ```python
257
+ from vibes_api import IngredientType
258
+ from vibes_api.ingredients import IngredientRef, CreateIngredient
259
+
260
+ # 1. By existing ingredient ID (from list_ingredients)
261
+ character = IngredientRef.by_id(
262
+ ingredient_id="800957099700717",
263
+ ingredient_type=IngredientType.CHARACTER,
264
+ name="Valdrin",
265
+ image_url="https://...",
266
+ )
267
+
268
+ # 2. By uploaded image entity ID (creates a new ingredient on-the-fly)
269
+ style = CreateIngredient.by_image_ent_id(
270
+ image_ent_id="1177...",
271
+ ingredient_type=IngredientType.STYLE,
272
+ name="Cyberpunk neon",
273
+ image_url="https://...",
274
+ )
275
+
276
+ # 3. By name only (uses prompt-generated image)
277
+ scene = CreateIngredient.by_name(
278
+ ingredient_type=IngredientType.SETTING,
279
+ name="Misty forest at dawn",
280
+ )
281
+
282
+ # Pass them to generate_video
283
+ batch = client.generate_video(
284
+ project_id=project["id"],
285
+ prompt="...",
286
+ ingredients=[character], # goes in `ingredients[]`
287
+ create_ingredients=[style, scene], # goes in `createIngredients[]`
288
+ )
289
+ ```
290
+
291
+ You can also CRUD ingredients directly:
292
+ - `client.list_characters()`, `list_styles()`, `list_scenes()`
293
+ - `client.create_ingredient(name, ingredient_type, source_image_ent_id, ...)`
294
+ - `client.delete_ingredient(ingredient_id)`
295
+
296
+ ---
297
+
298
+ ## 🖼️ Start/end frame (image-to-video with keyframes)
299
+
300
+ Generate a video that interpolates between two keyframes:
301
+
302
+ ```python
303
+ # Generate the start frame image
304
+ start_resp = client.generate_image(
305
+ project_id=project["id"],
306
+ prompt="a rose in full bloom",
307
+ aspect_ratio="16:9",
308
+ )
309
+ # Generate the end frame image
310
+ end_resp = client.generate_image(
311
+ project_id=project["id"],
312
+ prompt="a withered, dried rose",
313
+ aspect_ratio="16:9",
314
+ )
315
+
316
+ # Build frame handles
317
+ start_frame = client.build_frame_handle({
318
+ "mediaEntId": start_resp["data"][0]["imageEntId"],
319
+ "imageUrl": start_resp["data"][0]["url"],
320
+ })
321
+ end_frame = client.build_frame_handle({
322
+ "mediaEntId": end_resp["data"][0]["imageEntId"],
323
+ "imageUrl": end_resp["data"][0]["url"],
324
+ })
325
+
326
+ # Generate the video with both keyframes
327
+ batch = client.generate_video(
328
+ project_id=project["id"],
329
+ prompt="the rose slowly wilts, time-lapse effect",
330
+ start_frame=start_frame,
331
+ end_frame=end_frame,
332
+ aspect_ratio="16:9",
333
+ )
334
+ ```
335
+
336
+ For a single start frame (i2v without end frame), just omit `end_frame`.
337
+
338
+ ---
339
+
340
+ ## 🎥 Video extend (auto + manual)
341
+
342
+ The Vibes UI shows "Auto extend" and "Manual extend" buttons next to each generated video. Both call the same backend — the only difference is whether you supply a directive prompt:
343
+
344
+ ```python
345
+ # Get a previously-generated video's full content item
346
+ batch = client.get_batch("batch-...")
347
+ source_video = batch["content"][0]
348
+
349
+ # AUTO extend: no prompt, server continues original
350
+ extended_auto = client.extend_video(
351
+ project_id=project["id"],
352
+ source_video=source_video,
353
+ )
354
+
355
+ # MANUAL extend: provide a directive
356
+ extended_manual = client.manual_extend_video(
357
+ project_id=project["id"],
358
+ source_video=source_video,
359
+ prompt="camera pans up to reveal the sky",
360
+ )
361
+ ```
362
+
363
+ The `source_video` dict must be the full content item (not just an ID) because extend needs the original `videoHandle`, `videoGenEntId`, and `structuredOutput` from the source.
364
+
365
+ ---
366
+
367
+ ## 🔑 Authentication
368
+
369
+ Vibes uses a single cookie, `meta_session`, for authentication. The cookie value is a UUID session token.
370
+
371
+ ### How to get your cookie
372
+
373
+ 1. Log in at [vibes.ai](https://vibes.ai) in your browser (currently requires a Meta/Facebook account).
374
+ 2. Open DevTools (F12) → Application → Cookies → `https://vibes.ai`.
375
+ 3. Copy the value of `meta_session` (a long string with a UUID format like `e60e910a-...-K54E`).
376
+ 4. Pass it to the client:
377
+
378
+ ```python
379
+ client = VibesClient(meta_session="e60e910a-...")
380
+ ```
381
+
382
+ Or via env var:
383
+
384
+ ```bash
385
+ export VIBES_META_SESSION="e60e910a-..."
386
+ ```
387
+
388
+ ### Cookie rotation
389
+
390
+ Cookies **expire**. The web app refreshes them silently via `/api/auth/me`. When you start getting `401 Unauthorized` errors, grab a fresh cookie from the browser and create a new `VibesClient`. You said you'll rotate them — this is the only manual step.
391
+
392
+ ### TTS-specific limitation
393
+
394
+ The TTS endpoint (`/api/studio/playai/tts`) depends on a **server-side Facebook access token** that rotates independently of your `meta_session`. If you see `403 Facebook expired access token`, just wait a few minutes and retry. The Vibes backend auto-refreshes this token on its own schedule.
395
+
396
+ ---
397
+
398
+ ## 📡 API endpoint reference
399
+
400
+ All endpoints are under `https://vibes.ai/api/`. This list was extracted directly from the Next.js JS bundles.
401
+
402
+ ### Auth & system
403
+ - `GET /api/auth/me` — current user
404
+ - `POST /api/auth/logout` — invalidate session
405
+ - `POST /api/auth/check-token` — token validation
406
+ - `GET /api/system-status` — system status banner
407
+ - `POST /api/analytics` — usage analytics (fire-and-forget)
408
+ - `POST /api/bug-report` — bug reporting
409
+ - `POST /api/consent/record` — cookie consent
410
+ - `GET /api/quota/upsell` — upsell info
411
+
412
+ ### Projects
413
+ - `GET /api/projects` — list (params: `limit`, `offset`, `sort`, `search`)
414
+ - `POST /api/projects` — create
415
+ - `GET /api/projects/{id}` — get
416
+ - `PUT /api/projects/{id}` — update name/composition
417
+ - `DELETE /api/projects/{id}?deleteAssets=true` — delete
418
+ - `POST /api/projects/{id}/duplicate` — duplicate
419
+ - `POST /api/projects/{id}/upload` — bulk upload media
420
+ - `GET /api/projects/{id}/batches?limit=6&offset=0` — list batches in project
421
+ - `GET /api/projects/{id}/assets` — list project assets
422
+ - `POST /api/projects/{id}/assets` — add asset
423
+ - `POST /api/projects/{id}/assets/import` — import from another project
424
+ - `GET /api/projects/{id}/assets/available?sourceProjectId={id}` — list importable
425
+ - `POST /api/projects/{id}/timeline/download` — sync export to MP4
426
+ - `POST /api/projects/{id}/timeline/export-surfguard` — start async export
427
+ - `GET /api/projects/{id}/timeline/export/{exportId}/status` — poll export
428
+ - `POST /api/projects/{id}/timeline/export/{exportId}/cancel` — cancel
429
+
430
+ ### Generation batches
431
+ - `GET /api/generation-batches?limit=12&offset=0` — list (optional `projectId`, `type`)
432
+ - `POST /api/generation-batches` — create (body must include client-generated UUID v7 as `id`)
433
+ - `GET /api/generation-batches/{id}` — get full state
434
+ - `PUT /api/generation-batches/{id}` — update
435
+ - `DELETE /api/generation-batches/{id}` — delete
436
+ - `GET /api/generation-batches/{id}/stream` — SSE stream of batch updates
437
+
438
+ ### Generation
439
+ - `POST /api/generate/videos` — text-to-video, image-to-video, **extend**, **v2v edit**, **image animate** (all via different `type` and `config` values)
440
+ - `POST /api/generate/images` — text-to-image (synchronous)
441
+ - `POST /api/generate/image-edit` — edit an existing image
442
+ - `POST /api/generate/prompts` — prompt enhancement (returns 4 variations)
443
+ - `POST /api/animate/generate` — lip sync / animation
444
+
445
+ ### Studio
446
+ - `GET /api/studio/ingredients?ownerFilter=LIBRARY|VIEWER&ingredientType=...` — list ingredients
447
+ - `POST /api/studio/ingredients` — create ingredient
448
+ - `DELETE /api/studio/ingredients/{id}` — delete ingredient
449
+ - `GET /api/studio/voices` — list TTS voices
450
+ - `POST /api/studio/playai/tts` — text-to-speech (body: `{text, voice, outputFormat, language?}`)
451
+
452
+ ### Uploads
453
+ - `POST /api/upload-image` — base64 image upload (body: `{image: "<base64>"}`)
454
+ - `POST /api/upload-media` — multipart form (`file` + `filename`)
455
+ - `POST /api/upload-video-direct` — multipart form (`video`)
456
+ - `POST /api/upload-audio-direct` — multipart form (`audio`)
457
+ - `POST /api/upload-profile-picture` — profile picture
458
+
459
+ ### Media library & content items
460
+ - `GET /api/media-library?limit=50&offset=0&type=&sort=&search=` — list
461
+ - `GET /api/download/video?id={contentItemId}` — download video MP4
462
+ - `GET /api/download/png?id={contentItemId}` — download image PNG
463
+ - `GET /api/download/{type}?id={id}` — generic download
464
+ - `POST /api/content-items/{id}/favorite` — toggle favorite
465
+ - `POST /api/content-items/{id}/retry` — retry failed item
466
+ - `POST /api/content-items/{id}/feedback` — submit feedback
467
+ - `DELETE /api/content-items/{id}` — delete one
468
+ - `POST /api/content-items/bulk-delete` — bulk delete (body: `{ids: [...]}`)
469
+
470
+ ### Audio / music
471
+ - `GET /api/meta-music?q=&limit=&cursor=` — search Meta music library
472
+ - `GET /api/meta-music/lookup?id=&title=` — resolve track thumbnail
473
+ - `POST /api/meta-music/oa-check` — check original audio status
474
+ - `POST /api/media/music/clip` — clip a music track segment
475
+ - `POST /api/media/audio/clip` — clip any audio URL
476
+ - `GET /api/proxy-audio` — proxy audio through Vibes CDN
477
+ - `GET /api/resolve-audio-urls` — resolve audio CDN URLs
478
+
479
+ ### Moodboards & playables
480
+ - `GET /api/moodboards` — list
481
+ - `POST /api/moodboards` — create
482
+ - `GET /api/moodboards/{id}` — get
483
+ - `DELETE /api/moodboards/{id}` — delete
484
+ - `GET /api/playables` — list playables (currently disabled: `"Playables not enabled"`)
485
+
486
+ ### Timeline AI
487
+ - `POST /api/timeline/chat/stream` — streaming SSE chat (body: `{input, instructions, tools?, composition?}`)
488
+ - Event types: `message_delta`, `message_done`, `tool_call`, `tool_response`, `reasoning_delta`, `reasoning_done`, `completed`, `error`
489
+ - Default tools (sent by the client): `generate_image`, `generate_video`, `add_music`, `add_text_overlay`, `update_text_overlay`, `resize_clip`, `move_clip`, `extend_timeline_to`, `delete_clip`, `delete_track`, `split_clip`, `duplicate_clip`, `set_fade`, `set_volume`, `set_speed`, `mute_track`, `rename_track`, `reorder_clips`, `generate_lipsync`, `create_ingredient_from_clip`
490
+
491
+ ### Share & collaborators
492
+ - `POST /api/share-links` — create (body: `{entityType, entityId, expiresAt?, maxUses?}`)
493
+ - `GET /api/share-links?entityType=&entityId=` — list
494
+ - `DELETE /api/share-links/{id}` — revoke
495
+ - `GET /api/collaborators?entityType=&entityId=` — list
496
+ - `DELETE /api/collaborators/{id}` — remove
497
+
498
+ ### 🆕 Real-time sync (SSE)
499
+ - `GET /api/sync?entityType=&entityId=` — get last-updated timestamp
500
+ - `GET /api/sync/stream?entityType=&entityId=` — SSE stream of update events (`snapshot`, `update`, `bye`)
501
+
502
+ ### Settings
503
+ - `POST /api/settings/delete-account`
504
+ - `POST /api/settings/delete-all-media`
505
+ - `POST /api/settings/remove-all-posts`
506
+
507
+ ### Meta integration
508
+ - `POST /api/meta-graphql` — Meta GraphQL proxy (body: `{doc_id, variables}`)
509
+ - `POST /api/meta-oidc/start` — start OIDC flow
510
+ - `POST /api/meta-profiles/publish` — publish profile
511
+ - `POST /api/revisions` — session revisions
512
+
513
+ ---
514
+
515
+ ## 🧪 Examples
516
+
517
+ Ten ready-to-run example scripts in [`examples/`](./examples):
518
+
519
+ 1. **`01_generate_video.py`** — end-to-end video generation
520
+ 2. **`02_images_and_edits.py`** — image generation + editing + media library
521
+ 3. **`03_tts_and_lipsync.py`** — TTS → upload → lip sync pipeline
522
+ 4. **`04_prompts_and_chat.py`** — prompt enhancement + timeline AI chat
523
+ 5. **`05_ingredients.py`** — using saved characters in generations
524
+ 6. **`06_extend_video.py`** — 🆕 auto-extend and manual-extend a video
525
+ 7. **`07_ingredients_full.py`** — 🆕 character + style + scene combos
526
+ 8. **`08_create_ingredient.py`** — 🆕 create a new ingredient via API
527
+ 9. **`09_start_end_frame.py`** — 🆕 image-to-video with keyframe interpolation
528
+ 10. **`10_edit_video.py`** — 🆕 video-to-video editing (re-render with directive)
529
+
530
+ Run any of them with:
531
+
532
+ ```bash
533
+ export VIBES_META_SESSION="..."
534
+ python /home/z/my-project/download/vibes-api/examples/01_generate_video.py
535
+ ```
536
+
537
+ ---
538
+
539
+ ## ⚠️ Limitations & caveats
540
+
541
+ 1. **Cookie rotation** — `meta_session` expires. Re-grab from the browser when 401s appear.
542
+ 2. **TTS backend token** — `/api/studio/playai/tts` depends on a server-side FB token that rotates independently. If you get `403 Facebook expired access token`, wait and retry.
543
+ 3. **Generation quotas** — Vibes enforces per-user quotas (visible in the UI). Hit it and you'll get `429` or a `GENERATION_FAILED` with quota detail.
544
+ 4. **No public API** — All endpoints here are private and could change at any time. Pin to a client version if stability matters.
545
+ 5. **Content IDs for download** — `download_video(id)` expects the format `batch-{uuid}-content-{n}`. The client uses the `batch-` prefix consistently so this works for client-generated batches.
546
+ 6. **Rate limiting** — Don't hammer the API. The client uses a single `requests.Session`; if you need parallelism, instantiate multiple clients and rotate cookies.
547
+ 7. **Aspect ratios** — Only `1:1`, `9:16`, `16:9` are supported (server-enforced). Other values return `GENERATION_FAILED`.
548
+ 8. **Video extend requires full content item** — `extend_video(source_video=...)` needs the full content item dict (from `get_batch()`), not just an ID. The client extracts `videoHandle`, `videoGenEntId`, and `structuredOutput` from it.
549
+ 9. **v2v edit may fail on old videos** — `edit_video()` requires `videoHandle` metadata which older videos may not have. You'll get a clear error message in that case.
550
+ 10. **Sentry analytics** — The web app posts to Sentry for error tracking. This client does **not** replicate that (it's noise for API use).
551
+
552
+ ---
553
+
554
+ ## 🛠️ Development
555
+
556
+ ```bash
557
+ # Install in editable mode
558
+ pip install -e /home/z/my-project/download/vibes-api
559
+
560
+ # Run tests (requires VIBES_META_SESSION env var)
561
+ pytest
562
+
563
+ # Build CLI
564
+ python -m vibes_api.cli --help
565
+ ```
566
+
567
+ ### Project layout
568
+
569
+ ```
570
+ vibes-api/
571
+ ├── pyproject.toml
572
+ ├── README.md
573
+ ├── QUICKREF.md
574
+ ├── TEST_RESULTS.md
575
+ ├── vibes_api/
576
+ │ ├── __init__.py # Public API surface
577
+ │ ├── client.py # VibesClient main implementation (~2400 lines, 87 methods)
578
+ │ ├── cli.py # Argparse-based CLI
579
+ │ ├── models.py # Enums: AspectRatio, Resolution, VideoModel, etc.
580
+ │ └── ingredients.py # Ingredient payload builders
581
+ ├── examples/
582
+ │ ├── 01_generate_video.py
583
+ │ ├── 02_images_and_edits.py
584
+ │ ├── 03_tts_and_lipsync.py
585
+ │ ├── 04_prompts_and_chat.py
586
+ │ ├── 05_ingredients.py
587
+ │ ├── 06_extend_video.py # 🆕
588
+ │ ├── 07_ingredients_full.py # 🆕
589
+ │ ├── 08_create_ingredient.py # 🆕
590
+ │ ├── 09_start_end_frame.py # 🆕
591
+ │ └── 10_edit_video.py # 🆕
592
+ └── research/
593
+ └── ... (reversing notes, sample responses, screenshots)
594
+ ```
595
+
596
+ ---
597
+
598
+ ## 📜 License
599
+
600
+ MIT. This project is **not affiliated with Meta or Vibes**. Use at your own risk; respect Vibes' Terms of Service.