API Documentation

Everything you need to integrate film festival data into your application.

Base URL: https://festivalapi.com/v1

Authentication

All API requests (except /v1/health) require authentication via Bearer token. Include your API key in the Authorization header:

Authorization: Bearer ***

Get your API key from your Dashboard after signing up. Every account gets one key by default.

If your key is compromised, you can regenerate it from the API Keys page. The old key will stop working immediately.

Base URL

https://festivalapi.com/v1

All endpoints are relative to this base URL. HTTPS is required for all requests.

Prefer a marketplace? Festival API is also available on RapidAPI and as an Apify Actor.

Credits and Rate Limits

Festival API uses a pre-paid credit system. Each API call deducts credits from your balance based on the endpoint accessed.

EndpointCost
GET /v1/festivals1 credit
GET /v1/festivals/{id}5 credits
GET /v1/festivals/{id}/roster3 credits
GET /v1/festivals/scored10 credits
GET /v1/categories1 credit
GET /v1/countries1 credit
GET /v1/healthFree

When your credit balance reaches 0, API calls return HTTP 402 with a JSON body explaining the shortfall:

{
  "error": "insufficient_credits",
  "balance": 0,
  "required": 5,
  "message": "You need 5 credits. Purchase more at https://festivalapi.com/credits/pricing/"
}

Purchase credit packs from the pricing page. Credits expire 1 year after purchase.

Error Codes

StatusMeaningResponse
401Unauthorized{"detail": "Invalid API key"}
402Insufficient Credits{"error": "insufficient_credits", "balance": N, "required": M}
404Not Found{"error": "not_found"}
429Rate Limited{"detail": "Request was throttled"}
500Server Error{"detail": "A server error occurred"}
GET /v1/festivals 1 credit

Search and list film festivals. Returns up to 100 results. Filter by category using the category query parameter.

Query Parameters
ParameterTypeRequiredDescription
categorystringNoFestival category (e.g. short_film, feature, documentary, animation, horror, sci_fi)
countrystringNoCountry filter accepts full name or code, e.g. Australia/AU, Canada/CA, United States/US
genrestringNoAccepted genre (e.g. drama, comedy, experimental)
deadline_beforedateNoFilter by submission deadline before this date
deadline_afterdateNoFilter by submission deadline on or after this date
event_date_beforedateNoFilter by event start date before this date
fee_maxintegerNoMaximum submission fee in USD
submission_platformstringNoFilter by submission platform (e.g. filmfreeway, withoutabox)
statestringNoFilter by state or province (e.g. California, Ontario)
qstringNoFull-text search on festival name
sortstringNoSort field: name (default), deadline, or event_date
sort_dirstringNoSort direction: asc (default) or desc. Date sorts keep unknown dates last
๐Ÿ’ก Finding festivals accepting submissions: Use deadline_after=2026-09-09 to filter to festivals with upcoming deadlines โ€” equivalent to an "accepting submissions" filter. Combine with fee_max and category to narrow your search.
Code Examples
curl -H "Authorization: Bearer *** \
     "https://festivalapi.com/v1/festivals?category=short_film"
import requests

headers = {"Authorization": "Bearer *** }
resp = requests.get(
    "https://festivalapi.com/v1/festivals",
    params={"category": "short_film"},
    headers=headers
)
data = resp.json()
const resp = await fetch(
  "https://festivalapi.com/v1/festivals?category=short_film",
  { headers: { "Authorization": "Bearer *** } }
);
const data = await resp.json();
require 'net/http'
require 'json'

uri = URI("https://festivalapi.com/v1/festivals?category=short_film")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer *** result = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
data = JSON.parse(result.body)
req, _ := http.NewRequest("GET", "https://festivalapi.com/v1/festivals?category=short_film", nil)
req.Header.Set("Authorization", "Bearer *** client := &http.Client{}
resp, _ := client.Do(req)
Example Response
{
  "count": 47,
  "results": [
    {
      "id": 1,
      "name": "Sundance Film Festival",
      "year": 2026,
      "country": "United States",
      "city": "Park City",
      "state": "Utah",
      "categories": ["feature", "short_film", "documentary"],
      "genres": ["drama", "comedy", "horror"],
      "deadline_regular": "2026-09-15",

      "event_start_date": "2027-01-21",
      "event_dates": "January 21-31, 2027",
      "regular_fee": 85,
      "submission_platforms": ["FilmFreeway"],
      "submission_url": "https://filmfreeway.com/Sundance",
      "website": "https://festival.sundance.org",
      "composite_score": 94.5
    }
  ]
}
GET /v1/festivals/{id} 5 credits

Retrieve full details for a single film festival by ID. Includes submission info, categories, the primary deadline, standard fee, and festival details.

๐Ÿ’ก Note: Film roster (past screenings) is on a separate endpoint โ€” GET /v1/festivals/{id}/roster (3 credits).
Path Parameters
ParameterTypeRequiredDescription
idintegerYesFestival ID from list endpoint
Code Examples
curl -H "Authorization: Bearer *** \
     "https://festivalapi.com/v1/festivals/1/"
resp = requests.get(
    "https://festivalapi.com/v1/festivals/1/",
    headers={"Authorization": "Bearer *** }
)
const resp = await fetch(
  "https://festivalapi.com/v1/festivals/1/",
  { headers: { "Authorization": "Bearer *** } }
);
GET /v1/festivals/{id}/roster 3 credits

Returns films previously screened at this festival โ€” titles, directors, years, and awards. Separate from the festival detail endpoint. Use this to research what a festival programs. Supports page/per_page pagination.

Query Parameters
ParameterTypeRequiredDescription
pageintegerNoPage number (default: 1)
per_pageintegerNoResults per page (default: 20, max: 100)
Code Examples
curl -H "Authorization: Bearer *** \
     "https://festivalapi.com/v1/festivals/1/roster/"
resp = requests.get(
    "https://festivalapi.com/v1/festivals/1/roster/",
    headers={"Authorization": "Bearer *** }
)
const resp = await fetch(
  "https://festivalapi.com/v1/festivals/1/roster/",
  { headers: { "Authorization": "Bearer *** } }
);
Example Response
{
  "festival_id": 301,
  "festival_name": "Cambodia Town Film Festival",
  "count": 10,
  "page": 1,
  "per_page": 20,
  "total_pages": 1,
  "results": [
    {
      "id": 11,
      "festival_id": 301,
      "film_title": "Home Court",
      "film_director": "Erica Eng",
      "film_year": 2024,
      "film_genre": "",
      "film_category": "",
      "film_award": "Best Feature Documentary Film"
    },
    {
      "id": 12,
      "festival_id": 301,
      "film_title": "Meeting with Pol Pot",
      "film_director": "Rithy Panh",
      "film_year": 2025,
      "film_genre": "",
      "film_category": "",
      "film_award": "Opening Night Film"
    }
  ]
}
GET /v1/festivals/{id}/programming-profile 5 credits

Describes what a festival actually programs, based on its historical roster of screened and awarded films, rather than only what its listing says it accepts. Returns years analyzed, dominant categories, common award categories, programming trends (documentary, animation, experimental), sample size, and a confidence level so you can judge how much to rely on it.

This is the endpoint to call when you want the answer to: "Based on what this festival has actually screened, how well does my film fit?"

Always up to date: profiles are recomputed automatically whenever a festival's roster changes, so last_verified_at stays current without any action from you. If a festival has too little history to analyze (<3 roster entries), the endpoint returns a low-confidence "insufficient data" profile rather than an error.

What you get
  • sample_size, years_analyzed, year_range โ€” how much history was available.
  • dominant_categories โ€” e.g. short, feature, documentary, animation, student, with counts and shares.
  • common_award_categories and award_winners โ€” the award types the festival hands out.
  • programming_trends โ€” documentary, animation, experimental, and music-video share.
  • confidence and last_verified_at โ€” honesty metadata. Confidence is derived from sample size and data coverage.

Runtime length and production-country distribution are not reported because the festival roster data does not carry those fields. We only publish analytics supported by the historical data we have.

Code Examples
curl -H "Authorization: Bearer *** \
     "https://festivalapi.com/v1/festivals/2629/programming-profile/"
resp = requests.get(
    "https://festivalapi.com/v1/festivals/2629/programming-profile/",
    headers={"Authorization": "Bearer *** }
)
const resp = await fetch(
  "https://festivalapi.com/v1/festivals/2629/programming-profile/",
  { headers: { "Authorization": "Bearer *** } }
);
Example Response
{
  "festival_id": 2629,
  "festival_name": "Africa International Film Festival (AFRIFF)",
  "sample_size": 85,
  "years_analyzed_count": 4,
  "years_analyzed": [2021, 2023, 2024, 2025],
  "year_range": {"min": 2021, "max": 2025},
  "dominant_categories": [
    {"category": "short", "count": 43, "share": 0.5059},
    {"category": "feature", "count": 18, "share": 0.2118},
    {"category": "documentary", "count": 14, "share": 0.1647}
  ],
  "common_award_categories": [
    {"award_category": "Best Documentary Short", "count": 1}
  ],
  "programming_trends": [
    {"trend": "Documentary", "category": "documentary", "count": 14, "share": 0.1647},
    {"trend": "Animation", "category": "animation", "count": 5, "share": 0.0588}
  ],
  "runtime_analysis": null,
  "production_country_distribution": null,
  "confidence": "very_high",
  "last_verified_at": "2026-08-11T00:00:00Z",
  "notes": ["Profile derived from festival roster entries."]
}
GET /v1/festivals/scored 10 credits

Returns festivals ranked by their Festival Score (0-100). The score factors in category match, deadline proximity, fee reasonableness, and genre alignment. Useful for finding the best festivals to submit to. Supports page/per_page pagination (default: 20 per page, max: 100).

Query Parameters
ParameterTypeRequiredDescription
pageintegerNoPage number (default: 1)
per_pageintegerNoResults per page (default: 20, max: 100)
Code Examples
curl -H "Authorization: Bearer *** \
     "https://festivalapi.com/v1/festivals/scored/"
resp = requests.get(
    "https://festivalapi.com/v1/festivals/scored/",
    headers={"Authorization": "Bearer *** }
)

Countries

GET /v1/countries 1 credit

List all available countries with festival counts, ordered by count descending. Use this to discover which countries are covered, then filter by ?country= on the festivals endpoint.

curl -H "Authorization: Bearer YOUR_API_KEY" \
  https://festivalapi.com/v1/countries

Response:

{
  "count": 20,
  "results": [
    {"country": "United States", "festival_count": 48},
    {"country": "United Kingdom", "festival_count": 15},
    {"country": "Canada", "festival_count": 12},
    ...
  ]
}
GET /v1/countries 1 credit

List all countries with festival counts. Use the full country name to filter festivals with the country parameter on /v1/festivals.

GET /v1/countries

Response:

{
  "count": 70,
  "results": [
    {"country": "United States", "count": 448},
    {"country": "United Kingdom", "count": 48},
    {"country": "Canada", "count": 46},
    {"country": "India", "count": 35},
    {"country": "Germany", "count": 37},
    {"country": "Italy", "count": 33},
    ...
  ]
}
GET /v1/calendar 2 credits

A single unified feed of upcoming event dates and submission deadlines across all festivals, sorted by date. Power filmmaker calendars, submission CRMs, and embeddable festival widgets. Supports JSON and iCal (?export=ics) output so you can subscribe in Google/Apple Calendar.

Query Parameters
ParameterTypeRequiredDescription
startdateNoWindow start (YYYY-MM-DD). Default: today
enddateNoWindow end (YYYY-MM-DD). Default: today + 90 days
daysintegerNoAlternative to start/end: N days from today
categorystringNoFilter by category (e.g. short_film, documentary)
countrystringNoFilter by country
exportstringNoics returns an .ics calendar file
Code Examples
curl -H "Authorization: Bearer *** \
     "https://festivalapi.com/v1/calendar/?days=30"
resp = requests.get(
    "https://festivalapi.com/v1/calendar/?days=30",
    headers={"Authorization": "Bearer *** }
)
const resp = await fetch(
  "https://festivalapi.com/v1/calendar/?days=30",
  { headers: { "Authorization": "Bearer *** } }
);
Example Response
{
  "count": 12,
  "window": {"start": "2026-08-11", "end": "2026-09-10"},
  "results": [
    {
      "type": "deadline",
      "date": "2026-08-20",
      "deadline_stage": "regular",
      "festival_id": 301,
      "name": "Cambodia Town Film Festival",
      "city": "Long Beach", "state": "CA", "country": "United States",
      "categories": ["short_film", "feature", "documentary"],
      "submission_url": "https://filmfreeway.com/..."
    },
    {
      "type": "event",
      "date": "2026-09-05",
      "festival_id": 392,
      "name": "AFRIFF",
      "categories": ["feature", "documentary"]
    }
  ]
}
GET /v1/deadlines/closing-soon 2 credits

Festivals whose earliest upcoming submission deadline falls within the next N days. The nearest_deadline, deadline_stage, and days_remaining make it drop-in for email alerts, Slack/Discord notifications, and Zapier/n8n workflows that say "these deadlines close soon".

Query Parameters
ParameterTypeRequiredDescription
daysintegerNoLookahead window (default: 30, max: 90)
categorystringNoFilter by category
countrystringNoFilter by country
Code Examples
curl -H "Authorization: Bearer *** \
     "https://festivalapi.com/v1/deadlines/closing-soon/?days=14"
resp = requests.get(
    "https://festivalapi.com/v1/deadlines/closing-soon/?days=14",
    headers={"Authorization": "Bearer *** }
)
const resp = await fetch(
  "https://festivalapi.com/v1/deadlines/closing-soon/?days=14",
  { headers: { "Authorization": "Bearer *** } }
);
Example Response
{
  "count": 5,
  "results": [
    {
      "festival_id": 944,
      "name": "Berlin Short Film Festival",
      "city": "Berlin", "country": "Germany",
      "categories": ["short_film"],
      "submission_url": "https://...",
      "nearest_deadline": "2026-08-18",
      "deadline_stage": "late",
      "days_remaining": 7
    }
  ]
}
GET /v1/health Free

Health check endpoint. No authentication required. Returns 200 OK when the API is operational.

{"status": "ok", "service": "Festival API"}
GET /v1/categories 1 credit

List all available category codes. Use these codes to filter festivals with the category parameter on /v1/festivals.

GET /v1/categories

Response:

{
  "count": 158,
  "results": [
    {"category": "short_film", "count": 60},
    {"category": "feature", "count": 55},
    {"category": "documentary", "count": 31},
    {"category": "animation", "count": 14},
    {"category": "horror", "count": 12},
    {"category": "sci_fi", "count": 5},
    {"category": "comedy", "count": 5},
    ...
  ]
}

Integrations & Open-Source Examples

Need help wiring this into your site?

Our team can implement Festival API for you, from a quick integration to a full build. Explore Implementation Services โ†’

๐Ÿ Python Client

Zero-dependency Python client. Install and query in two lines:

pip install festivalapi

Usage:

from festivalapi import FestivalAPI

client = FestivalAPI("fes_your_api_key")

# Search festivals
festivals = client.festivals.list(category="short_film")

# Keyword search
results = client.festivals.list(q="Cambodia")

# Get scored festivals
scored = client.festivals.scored(min_score=70)

# Get a festival's film roster
roster = client.festivals.roster(301)

# Health check (no auth)
client.health()

List available category codes:

# Get all category codes
categories = client.categories()
for cat in categories["results"]:
    print(f'{cat["category"]} ({cat["count"]})')

List available countries:

# Get all countries with festival counts
countries = client.countries()
for c in countries["results"]:
    print(f'{c["country"]} ({c["count"]})')

Common codes: short_film, feature, documentary, animation, horror, sci_fi, comedy, experimental, music_video, ai, web_series, student, lgbtq, vr_360.

PyPI ยท Integration page

โฌก Node.js Client

Zero-dependency Node.js client (built-in fetch, no HTTP library needed):

npm install festivalapi

Usage:

import { FestivalAPI } from "festivalapi";

const client = new FestivalAPI("fes_your_api_key");

// Search festivals
const festivals = await client.festivals.list({ category: "short_film" });

// Get scored festivals
const scored = await client.festivals.scored({ min_score: 70 });

// Get a festival's film roster
const roster = await client.festivals.roster(301);

// Health check (no auth)
const health = await client.health();

npm ยท Integration page

๐Ÿค– Apify Actor

Run Festival API as a serverless Apify Actor. Search, filter, and export festival data directly from the Apify platform โ€” no code required.

Apify Store — schedule recurring runs, export to JSON/CSV, connect via webhook ยท Integration page

โšก RapidAPI

Use Festival API through RapidAPI if you want marketplace billing, built-in testing, and generated sample code.

RapidAPI Listing ยท Integration page

๐Ÿ“˜ APIDog (Interactive Docs)

Interactive API documentation with live endpoint testing, auto-generated code snippets in cURL, JavaScript, Python, and more. Browse and test every endpoint from your browser.

Open APIDog โ†’ ยท Integration page

๐Ÿ”ท Apyhub

Browse and test Festival API on Apyhub with an interactive playground, live responses, and one-key billing across the full Apyhub catalog. 6 GET endpoints exposed.

View on Apyhub โ†’ ยท Integration page

โšก Zapier Integration

Connect Festival API to Slack, Gmail, Google Sheets, and 9000+ apps via Zapier. No code required. Now live on Zapier.

Available actions:

  • Search Festivals โ€” find festivals by name, category, or country
  • Look Up Festival Detail โ€” get full details (dates, location, standard fee, score)
  • Look Up Festival Roster โ€” get the first film entry in a festival's programming roster

To use:

  1. Use the Festival API app on Zapier to add the integration
  2. Use Schedule by Zapier as your trigger (for daily digests or alerts)
  3. Add a Festival API action and select one of the actions above
  4. Connect your Festival API key from your Dashboard
  5. Choose a destination (Slack, Email, Google Sheets, etc.)
# Example: daily festival discovery digest
# Trigger: Schedule by Zapier at 9am daily
# Action 1: Festival API โ†’ Search Festivals
#   query: "Sundance"
# Action 2: Send to Slack / Email / Google Sheets

Try it on Zapier โ†’ ยท Integration page

๐Ÿ”— n8n Node

Use Festival API in your n8n workflows โ€” search festivals, look up details, and explore film rosters with the verified n8n node. In n8n Cloud, just search "Festival API" in the node panel to add it.

npm install n8n-nodes-festivalapi

For self-hosted n8n, install via Settings โ†’ Community Nodes, or find it on npm:

npm โ†’ ยท Integration page

๐Ÿ›’ API.market

Discover and evaluate Festival API through API.market, with marketplace access for teams that prefer marketplace procurement and billing.

View on API.market โ†’ ยท Integration page

๐Ÿ”Œ REST API

Festival API is plain REST/JSON with Bearer token auth. Use any HTTP client.