Let users choose a canvas
Use the Public API to list or search canvases, then create an embed session for the selected canvas. A canvas in either response is aCanvasItem. The title field is name (not title), and neither endpoint returns a thumbnail — render the picker from name/category/updated_at, or open the canvas to get a preview.
CanvasItem
data, search is a flat list under canvases:
List canvases — { data, next_cursor }
Search canvases — { canvases }
next_cursor until it comes back null:
Build a canvas picker
Recommended flow:- User opens your “Choose design” screen.
- Your backend calls
GET /v1/canvasesorGET /v1/canvases/search. - Your frontend shows the result list.
- User selects a canvas.
- Your backend creates an embed session for that canvas.
- Your frontend loads the returned
embed_url.
Restrict canvases in an internal tool
Your app should remain the policy decision point. Moda can pin an embed session to one canvas, one mode, and one set of allowed browser origins, but your backend should decide which internal users may see or edit each canvas before creating the session. Recommended pattern:- Store the mapping between your internal users, teams, projects, or roles and the Moda canvas IDs they may access.
- When a user opens your picker, call the Moda Public API from your backend and filter the results against that mapping before returning them to the browser.
- When the browser asks to open a canvas, do not trust the submitted
canvas_id. Re-check the current internal user against your access mapping on the backend. - Create the embed session only after that check passes.
- Set
modefrom your app’s authorization result. For example, reviewers getview-no-exportorview; editors getedit. - Set
external_user.idto your stable internal user ID for attribution and audit trails. - Revoke active sessions when the user signs out, changes role, or loses access to the underlying project.
Backend authorization sketch
Save and autosave
Edit-mode embeds autosave after user edits. You can still call manual save before an important transition:canvas:saved before closing a modal or advancing your workflow:
Use your own chat UI
Create sessions with:chat.stop to cancel the active agent turn.
Insert user-uploaded images
If the user picks an image in your app, send theFile to the iframe. The iframe uploads it through the embed image endpoint and inserts a real Moda image node.
Embed uploads currently accept PNG, JPEG, GIF, and WebP files up to 25 MB. If you need SVG or larger asset handling, upload through your own workflow and pass a browser-renderable HTTPS URL to insertImage.
Insert server-generated images
If your backend generates an image, prefer one of these:
Example with a URL:
Export from the iframe
Use iframe export when the user needs the file immediately in the browser.export:completed includes a dataUrl — the whole file inline as base64, with no size cap. This is fine for a single image, but a multi-page PDF/PPTX can be many megabytes in memory and is capped by a ~120s completion timeout.
Use Public API export when your backend needs a durable export URL, background polling, caching, a server-side workflow, or whenever the document is large or multi-page:
Refresh long-running sessions
Sessions can last up to 3600 seconds. For long editing sessions:- Track
expires_atfrom session creation. - Set a timer to refresh from your backend before expiry (for example, 60s ahead).
- Send the new token to the iframe with
session.refresh; the iframe repliessession:refreshed { expiresAt }.
Revoke on logout or close
Call revoke when access should end:Should you build an API wrapper?
Most teams do best with two small clients:
Avoid a browser SDK that exposes general Moda API calls. It would either leak your API key or require your backend to proxy every possible operation.
A backend wrapper is useful if your app uses several Public API endpoints: