GeoTasker API

Generate animated geospatial story videos programmatically. Create narrated explainer videos with maps, charts, and data visualizations.

https://geotasker.ai/api/v1v1 Stable
Get API Key

Authentication

All requests require an API key. Pass it via the X-API-Key header or as a Bearer token.

MethodExample
Header (preferred)X-API-Key: gt_live_a1b2c3...
Bearer tokenAuthorization: Bearer gt_live_a1b2c3...

API keys use the format gt_live_<64 hex chars>. Keys are created from your dashboard and can have scopes:

  • render — required for POST /render
  • generate — required for POST /generate
curl https://geotasker.ai/api/v1/videos \
  -H "X-API-Key: gt_live_your_key_here"

Rate Limits

Limits are enforced per API key using a sliding window. When exceeded, the API returns 429 with a Retry-After header.

TierPer MinutePer HourPer Day
Free52050
Pro302001,000
Enterprise1001,00010,000

POST /render

POST/api/v1/renderRender a story JSON directly into a video (no AI)

Submit a complete story JSON and render it into a narrated video. No AI agent is involved — your story is rendered as‑is. Requires the render scope.

Request Body

FieldTypeDescription
storyrequiredobjectStory JSON in MultiSegmentStory format
optionsobjectRender options (see below)
options.narrationbooleanEnable AI narration Default: true
options.background_musicbooleanEnable background music Default: true
options.music_stylestringMusic style: Cinematic, Ambient, Classical, Jazz, Electronic, etc. Default: "Cinematic"
options.resolutionstringVideo resolution Default: "1080p"
options.fpsintegerFrames per second (24-60) Default: 30
options.languagestringNarration language code (en, bn, hi, etc.) Default: "en"
webhook_urlstringURL to POST when render completes or fails

Response

FieldTypeDescription
idstringVideo task ID for polling
statusstringAlways "accepted" on success
poll_urlstringRelative URL to poll for status
estimated_duration_secondsintegerEstimated render time (~180s)
curl -X POST https://geotasker.ai/api/v1/render \
  -H "X-API-Key: gt_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "story": {
      "segments": [
        {
          "type": "map",
          "estimated_duration": 10,
          "narration": "The Silk Road stretched across Central Asia...",
          "renderer": "mapbox",
          "story": {
            "camera": {
              "center": [65, 40],
              "zoom": 3,
              "keyframes": [
                {"at": 0, "center": [30, 35], "zoom": 4},
                {"at": 10, "center": [110, 35], "zoom": 4}
              ]
            }
          }
        }
      ]
    },
    "options": {
      "resolution": "1080p",
      "music_style": "Cinematic"
    }
  }'

POST /generate

POST/api/v1/generateAI generates a story from a text prompt, then renders

Describe what you want in plain text. The AI agent creates the story JSON, gathers geospatial data, and renders the video. Requires the generate scope.

Request Body

FieldTypeDescription
promptrequiredstringText description of the video (10-5,000 chars)
optionsobjectRender options (same as /render)
webhook_urlstringURL to POST when render completes or fails

Response

Same shape as POST /render. Estimated duration is ~300s since the AI agent needs time to generate the story.

curl -X POST https://geotasker.ai/api/v1/generate \
  -H "X-API-Key: gt_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Create a 60-second video about why the US wants Greenland, showing the Arctic military bases and natural resources",
    "options": {
      "resolution": "1080p",
      "language": "en"
    }
  }'

GET /videos/{id}

GET/api/v1/videos/{id}Poll render status and get the result

Poll this endpoint until status is "completed" or "failed". We recommend polling every 5–10 seconds.

Status Lifecycle

acceptedrenderingcompletedorfailed

Response

FieldTypeDescription
idstringVideo task ID
statusstringaccepted | rendering | completed | failed
progressinteger | nullRender progress 0-100 (when rendering)
messagestring | nullCurrent step description
video_urlstring | nullPresigned S3 URL (valid 1 hour, only when completed)
duration_secondsnumber | nullVideo duration (when completed)
render_time_secondsnumber | nullTime spent rendering (when completed)
errorstring | nullError message (when failed)
created_atstringISO 8601 timestamp
# Poll until completed
curl https://geotasker.ai/api/v1/videos/YOUR_TASK_ID \
  -H "X-API-Key: gt_live_your_key_here"

# Example response (rendering):
# {"id":"...","status":"rendering","progress":45,"message":"Rendering segment 3/8..."}

# Example response (completed):
# {"id":"...","status":"completed","video_url":"https://...","duration_seconds":62.5}

GET /videos

GET/api/v1/videosList recent videos

Returns your most recent videos (last 7 days), ordered newest first.

Query Parameters

ParamTypeDescription
limitintegerMax videos to return Default: 20

Response

Array of video objects:

FieldTypeDescription
idstringVideo task ID
statusstringaccepted | rendering | completed | failed
sourcestring"render" or "generate"
created_atstringISO 8601 timestamp
video_urlstring | nullPresigned URL (when completed)
curl "https://geotasker.ai/api/v1/videos?limit=5" \
  -H "X-API-Key: gt_live_your_key_here"

Story JSON Schema

The story object passed to /render follows the MultiSegmentStory format. A story consists of an array of segments, each rendered sequentially into the final video.

Segment Types

TypeRenderersDescription
mapmapbox, folium, kepler, deckgl, customAnimated map with camera movements, markers, routes
texthtml, pilTitle cards, fact screens, text overlays
chartmatplotlib, chart.js, d3Bar, line, pie, donut, racing bar charts
codemanim, custom pythonMathematical animations, custom visualizations

Full Example

{
  "segments": [
    {
      "type": "text",
      "estimated_duration": 5,
      "narration": "The ancient Silk Road connected East and West for centuries.",
      "title": "The Silk Road",
      "subtitle": "A Journey Through Time",
      "style": "cinematic"
    },
    {
      "type": "map",
      "estimated_duration": 15,
      "narration": "Starting from Chang'an in China, merchants traveled westward through Central Asia, carrying silk, spices, and precious stones.",
      "renderer": "mapbox",
      "story": {
        "camera": {
          "center": [65, 40],
          "zoom": 3,
          "pitch": 45,
          "bearing": 0,
          "keyframes": [
            {"at": 0, "center": [108, 34], "zoom": 5, "pitch": 60},
            {"at": 8, "center": [65, 39], "zoom": 4, "pitch": 45},
            {"at": 15, "center": [28, 41], "zoom": 5, "pitch": 60}
          ]
        },
        "entities": [
          {
            "type": "marker",
            "coordinates": [108.94, 34.26],
            "label": "Chang'an",
            "start_at": 0
          },
          {
            "type": "marker",
            "coordinates": [28.97, 41.01],
            "label": "Constantinople",
            "start_at": 12
          }
        ]
      }
    },
    {
      "type": "chart",
      "estimated_duration": 8,
      "narration": "Trade volume grew significantly between the 2nd century BCE and the 14th century CE.",
      "chart_type": "line",
      "data": {
        "labels": ["200 BCE", "0 CE", "200 CE", "600 CE", "1000 CE", "1400 CE"],
        "datasets": [
          {
            "label": "Relative Trade Volume",
            "data": [10, 30, 55, 40, 70, 85]
          }
        ]
      },
      "title": "Silk Road Trade Over Time"
    }
  ]
}

Error Codes

All errors return a JSON body with an error object containing a code and message.

{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded (5 requests per min). Upgrade tier for higher limits.",
    "retry_after": 42
  }
}
HTTPCodeDescription
401MISSING_API_KEYNo API key provided in headers
401INVALID_API_KEYAPI key not recognized or wrong format
403KEY_REVOKEDAPI key has been revoked
403INSUFFICIENT_SCOPEAPI key missing required scope (render or generate)
404NOT_FOUNDVideo not found or not owned by your key
429RATE_LIMIT_EXCEEDEDToo many requests. Check Retry-After header
500RENDER_FAILEDRender pipeline error
500GENERATE_FAILEDAI generation pipeline error
503SERVER_BUSYAll render slots in use. Retry after ~60 seconds

MCP Server

GeoTasker exposes an MCP (Model Context Protocol) server so AI coding tools can generate geospatial videos directly from your IDE.

Any MCP-compatible client works — including Claude Code, Cursor, VS Code Copilot, and Windsurf.

https://geotasker.ai/mcp/mcpStreamable HTTP

MCP Quick Start

One command to connect. Your browser will open for Google sign-in, and you're ready to go.

Claude Code

claude mcp add --transport http geotasker https://geotasker.ai/mcp/mcp

Cursor / VS Code Copilot

Add to your .cursor/mcp.json or VS Code MCP settings:

{
  "mcpServers": {
    "geotasker": {
      "url": "https://geotasker.ai/mcp/mcp"
    }
  }
}

Generic MCP Client

Any client that supports Streamable HTTP transport can connect:

{
  "mcpServers": {
    "geotasker": {
      "transport": "http",
      "url": "https://geotasker.ai/mcp/mcp"
    }
  }
}

MCP Authentication

MCP uses OAuth 2.1 with PKCE — no API keys needed. Authentication is handled automatically by your MCP client.

1.

Connect

Add the MCP server URL to your client

2.

Browser sign-in

Your browser opens automatically for Google sign-in

3.

Done

Tokens refresh automatically. No keys to manage or rotate

MCP Tools

Four tools are available through the MCP server. Your AI assistant can call these directly.

TOOLgenerate_videoGenerate a video from a text prompt

Describe what you want in plain text. AI creates the story, gathers map data, and renders the video.

ParameterTypeDescription
promptrequiredstringText description of the video (min 10 chars)
narrationbooleanInclude AI narration Default: true
background_musicbooleanInclude background music Default: true
music_stylestringCinematic, Ambient, Classical, Jazz, Rock, Electronic, Pop, Folk, World, Orchestral Default: "Cinematic"
resolutionstringVideo resolution Default: "1080p"
TOOLrender_videoRender a video from a story JSON

Submit a complete GeoTasker story JSON. No AI involved — your story is rendered as-is.

ParameterTypeDescription
storyrequiredobjectGeoTasker MultiSegmentStory JSON object
narrationbooleanInclude AI narration Default: true
background_musicbooleanInclude background music Default: true
music_stylestringMusic style Default: "Cinematic"
resolutionstringVideo resolution Default: "1080p"
TOOLget_video_statusCheck video generation status

Poll until status is completed or failed.

ParameterTypeDescription
video_idrequiredstringThe task/video ID returned by generate_video or render_video
TOOLlist_videosList your recent videos

Returns videos created via the API in the last 7 days.

ParameterTypeDescription
limitintegerMax number of videos to return (1-50) Default: 10