Skip to main content

Export pipeline

Problem: Archive every canvas on the team as a PDF. Upload each to S3 / Google Drive. Skip canvases that have an in-flight design task.

Primitives

  • GET /v1/canvases — cursor-paginate all canvases
  • POST /v1/canvases/{id}/export?format=pdfsynchronous; returns a signed URL
  • Handle 409 canvas_active_job — back off and retry
  • Upload the file bytes to your storage of choice

TypeScript (Node 20+)

Python (httpx)

Gotchas

  • Export is synchronous. No task polling. One POST returns the signed URL (or a retryable 409).
  • Signed URLs expire after 7 days. Download and re-upload immediately — don’t persist the signed URL itself.
  • 409 canvas_active_job is the retry signal when a design task is running on the canvas. Respect Retry-After (default 10s).
  • 429 rate_limited applies per-endpoint — exports have their own cap (25/min by default, raisable per-org; see Usage Limits). Respect Retry-After.
  • Cursor pagination is sequential. Can’t parallelize page fetches. Parallelize the per-canvas work within a page instead (cap to ~4–8 concurrent exports).
  • Scope requirements: canvases:read for listing, designs:export for the export endpoint. Team membership required — a share-token-only caller can’t export.
  • Don’t export the same canvas twice in a row. If you re-run this job often, compare updated_at against your archive and skip unchanged canvases.
If you only want canvases matching a pattern:
/canvases/search is also cursor-paginated.

See also