List Projects
curl --request GET \
--url https://app.nouvel.ai/api/v1/projectsimport requests
url = "https://app.nouvel.ai/api/v1/projects"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://app.nouvel.ai/api/v1/projects', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.nouvel.ai/api/v1/projects",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://app.nouvel.ai/api/v1/projects"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://app.nouvel.ai/api/v1/projects")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.nouvel.ai/api/v1/projects")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body{
"projects": [
{
"id": "<string>",
"title": "<string>",
"description": {},
"status": "<string>",
"final_output_url": {},
"aspect_ratio": {},
"target_duration_seconds": {},
"product_url": {},
"created_at": "<string>",
"updated_at": "<string>"
}
],
"pagination": {
"page": 123,
"limit": 123,
"total": 123,
"totalPages": 123,
"hasMore": true
}
}Projects
List Projects
Retrieve a paginated list of your video ad projects
GET
/
api
/
v1
/
projects
List Projects
curl --request GET \
--url https://app.nouvel.ai/api/v1/projectsimport requests
url = "https://app.nouvel.ai/api/v1/projects"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://app.nouvel.ai/api/v1/projects', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.nouvel.ai/api/v1/projects",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://app.nouvel.ai/api/v1/projects"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://app.nouvel.ai/api/v1/projects")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.nouvel.ai/api/v1/projects")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body{
"projects": [
{
"id": "<string>",
"title": "<string>",
"description": {},
"status": "<string>",
"final_output_url": {},
"aspect_ratio": {},
"target_duration_seconds": {},
"product_url": {},
"created_at": "<string>",
"updated_at": "<string>"
}
],
"pagination": {
"page": 123,
"limit": 123,
"total": 123,
"totalPages": 123,
"hasMore": true
}
}Returns a paginated list of all video ad projects created by the authenticated user. Results are sorted by creation date (newest first) and can be filtered by project status.
Authentication
This endpoint requires a valid API key with theprojects:read permission.
Authorization: Bearer nvl_xxxx
Query Parameters
integer
default:1
Page number for pagination (1-indexed). Must be a positive integer.
integer
default:20
Number of results to return per page. Must be between 1 and 100.
string
Filter projects by their current status. Omit to return all projects.Allowed values:
generating- Video scenes are being generatedpost_processing- Generating voiceover and lip syncstitching- Combining scenes with audio and captionscompleted- Project is ready with final videofailed- Generation encountered an unrecoverable errorpartial- Some scenes completed but project failed overall
Response
array
List of project objects matching the query criteria.
Show Project object properties
Show Project object properties
string
Unique project identifier (UUID format).
string
Human-readable project title.
string | null
AI-generated description of the video ad concept. May be
null for projects still in generation.string
Current project status. One of:
generating, post_processing, stitching, completed, failed, partial.string | null
HTTPS URL to the final MP4 video file. Only available when
status is completed. URL is publicly accessible but unguessable.string | null
Video aspect ratio. Common values:
"9:16" (vertical/mobile), "1:1" (square), "16:9" (horizontal/desktop).integer | null
Target video duration in seconds. Actual duration may vary slightly.
string | null
Original product URL provided when creating the project.
string
ISO 8601 timestamp when the project was created.
string
ISO 8601 timestamp when the project was last modified.
object
Pagination metadata for navigating through results.
Example Requests
curl https://app.nouvel.ai/api/v1/projects \
-H "Authorization: Bearer nvl_xxxx"
curl "https://app.nouvel.ai/api/v1/projects?status=completed&limit=10" \
-H "Authorization: Bearer nvl_xxxx"
curl "https://app.nouvel.ai/api/v1/projects?page=2&limit=50" \
-H "Authorization: Bearer nvl_xxxx"
const response = await fetch('https://app.nouvel.ai/api/v1/projects', {
headers: {
'Authorization': 'Bearer nvl_xxxx'
}
});
const data = await response.json();
console.log(`Found ${data.pagination.total} projects`);
const response = await fetch(
'https://app.nouvel.ai/api/v1/projects?status=completed',
{
headers: {
'Authorization': 'Bearer nvl_xxxx'
}
}
);
const data = await response.json();
const completedVideos = data.projects.map(p => ({
id: p.id,
title: p.title,
videoUrl: p.final_output_url
}));
async function getAllProjects() {
const allProjects = [];
let page = 1;
let hasMore = true;
while (hasMore) {
const response = await fetch(
`https://app.nouvel.ai/api/v1/projects?page=${page}&limit=100`,
{
headers: {
'Authorization': 'Bearer nvl_xxxx'
}
}
);
const data = await response.json();
allProjects.push(...data.projects);
hasMore = data.pagination.hasMore;
page++;
}
return allProjects;
}
import requests
response = requests.get(
'https://app.nouvel.ai/api/v1/projects',
headers={'Authorization': 'Bearer nvl_xxxx'}
)
data = response.json()
print(f"Found {data['pagination']['total']} projects")
import requests
response = requests.get(
'https://app.nouvel.ai/api/v1/projects',
params={'status': 'completed', 'limit': 10},
headers={'Authorization': 'Bearer nvl_xxxx'}
)
data = response.json()
for project in data['projects']:
print(f"{project['title']}: {project['final_output_url']}")
import requests
def get_all_projects():
all_projects = []
page = 1
has_more = True
while has_more:
response = requests.get(
'https://app.nouvel.ai/api/v1/projects',
params={'page': page, 'limit': 100},
headers={'Authorization': 'Bearer nvl_xxxx'}
)
data = response.json()
all_projects.extend(data['projects'])
has_more = data['pagination']['hasMore']
page += 1
return all_projects
Example Response
{
"projects": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Premium Collagen Ad - Vertical",
"description": "A compelling 15-second ad showcasing the benefits of marine collagen supplement with professional spokesperson and product demo.",
"status": "completed",
"final_output_url": "https://app.nouvel.ai/api/cdn/videos/final-550e8400.mp4",
"aspect_ratio": "9:16",
"target_duration_seconds": 15,
"product_url": "https://example.com/products/collagen",
"created_at": "2026-03-15T14:32:10.000Z",
"updated_at": "2026-03-15T14:48:22.000Z"
},
{
"id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
"title": "Skincare Serum - Instagram",
"description": null,
"status": "generating",
"final_output_url": null,
"aspect_ratio": "9:16",
"target_duration_seconds": 15,
"product_url": "https://example.com/products/serum",
"created_at": "2026-03-15T14:20:05.000Z",
"updated_at": "2026-03-15T14:25:18.000Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 42,
"totalPages": 3,
"hasMore": true
}
}
Notes
Security: Only projects belonging to the authenticated user are returned. API keys are scoped to individual user accounts.
Video Availability: The
final_output_url is only populated when the project status is completed. For projects still in progress, this field will be null.Sorting: Results are always sorted by
created_at in descending order (newest projects first). Custom sorting is not currently supported.Rate Limiting: This endpoint is rate-limited to 60 requests per minute per API key. See Rate Limits for details.

