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 canvasesPOST /v1/canvases/{id}/export?format=pdf— synchronous; 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_jobis the retry signal when a design task is running on the canvas. RespectRetry-After(default 10s).429 rate_limitedapplies per-endpoint — exports have their own cap (25/min by default, raisable per-org; see Usage Limits). RespectRetry-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:readfor listing,designs:exportfor 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_atagainst your archive and skip unchanged canvases.
Variant: filter by search
If you only want canvases matching a pattern:/canvases/search is also cursor-paginated.
See also
../references/canvases-and-exports.md— export semantics, 409 pattern../references/pagination.md../references/errors.md— rate-limit handling