Poll for results

Understanding how to work with Gamma’s asynchronous API and poll for results

Gamma generation is asynchronous. You start a generation, receive a generationId immediately, then poll the status endpoint until the result is ready.

Quick reference

  • POST /v1.0/generations returns generationId only.

  • Poll GET /v1.0/generations/{generationId} every 5 seconds until status is completed or failed.

  • gammaUrl and exportUrl are only available from the completed status response.

  • Export URLs are signed and expire after approximately one week. Download exported files promptly.

The basic flow

POST /generations      →  Returns { generationId: "abc123" }
Wait ~5 seconds
GET /generations/abc123  →  Returns { status: "pending" }
Wait ~5 seconds  
GET /generations/abc123  →  Returns { status: "completed", gammaUrl: "...", exportUrl: "..." }

What you get back

When status is completed, the response includes:

Field
Description

gammaUrl

Direct link to view/share the presentation in Gamma

exportUrl

Download URL for the exported file (if exportAs was specified)

Generation states

Status
Meaning
What to Do

pending

Still generating

Keep polling every 5 seconds

completed

Done!

Stop polling — use gammaUrl and export URLs

failed

Something went wrong

Stop polling, check the error object

Code examples

Using automation platforms

Popular automation platforms have built-in ways to handle delays and polling:

Zapier

Use the Delay action between your HTTP Request steps:

  1. HTTP Request (POST) → Start generation, get generationId

  2. Delay for → Wait 30-60 seconds

  3. HTTP Request (GET) → Check status with the generationId

  4. Use Paths or Filter to check if status equals completed

  5. If still pending, use Looping by Zapier to repeat steps 2-4

Zapier's "Delay for" action pauses your Zap for a specified time (minimum 1 minute). For most Gamma generations, a single 60-second delay followed by a status check works well.

Make (formerly Integromat)

Use the Sleep module or a polling pattern:

  1. HTTP module → POST to start generation

  2. Sleep module → Wait 30 seconds

  3. HTTP module → GET to check status

  4. Router with filter → Check if status is completed

  5. Use Repeater + Sleep for polling loop

n8n

Use the Wait node with time interval:

  1. HTTP Request node → POST to start generation

  2. Wait node → Set to "After Time Interval" (30-60 seconds)

  3. HTTP Request node → GET to check status

  4. IF node → Check status === "completed"

  5. Loop back to Wait node if still pending

n8n's Wait node offloads execution data to the database during longer waits, so your workflow won't timeout even for complex generations.

Best practices

  • Use 5-second polling intervals. Polling more frequently will not speed up the generation and may increase the chance of rate limiting.

  • Set a maximum timeout. Most generations complete within 2-3 minutes, so a 5-minute ceiling is a good default for automation.

  • Handle all three states: pending, completed, and failed.

  • Use exponential backoff if you receive a 429 response.

Rate limit headers and adaptive polling

Every API response includes headers that show your current rate limit usage. Use these to adjust your polling speed dynamically instead of waiting for a 429 error.

To see these headers in curl, add the -i flag. You can also use -v for full verbose output including request headers and TLS details, but -i is cleaner for inspecting rate limits.

Without -i, you'd only see the JSON body. The headers are always present — -i just tells curl to display them. In Python, JavaScript, or any HTTP client, these headers are always accessible on the response object without any special flag.

Header
Description

x-ratelimit-limit-burst

Maximum requests allowed in the current short window

x-ratelimit-remaining-burst

Requests remaining in the current short window

x-ratelimit-limit

Maximum requests allowed per hour

x-ratelimit-remaining

Requests remaining in the current hour

x-ratelimit-limit-daily

Maximum requests allowed per day

x-ratelimit-remaining-daily

Requests remaining today

Adaptive polling example

Instead of a fixed 5-second interval, read x-ratelimit-remaining-burst and slow down when capacity is low:

circle-info

Generation time varies. Larger decks, AI-generated images, and higher-quality image models all increase generation time. A 5-card deck with no images may complete in under a minute, while a 40-card deck with AI images could take several minutes. Factor this into your timeout and polling logic — there is no single "right" interval for all requests.

Handling a 429 response

If you hit the rate limit, the API returns 429 Too Many Requests. Pause for 30 seconds before retrying, then use exponential backoff if subsequent requests also return 429.

Common issues

status stays pending for too long

Generations typically complete in 1-3 minutes. If you are waiting longer than 5 minutes:

  • Check that you're polling the correct generationId

  • Verify your API key has sufficient credits

  • Try generating with fewer cards (numCards) to test

You receive a 429 rate-limit response

If you receive a 429 error:

  • Use 5+ second polling intervals

  • Use curl -i to check the x-ratelimit-remaining-burst header and see if you're near the limit

  • See Rate limit headers and adaptive polling above for how to throttle dynamically

  • If you're using Zapier, Make, or n8n, the rate limit may be on the platform side rather than Gamma's

Last updated

Was this helpful?