Aller au contenu
FR
On this page

Studio in an iframe

Offer DokKraft document editing inside your own product: the studio loads in an iframe on your domains, authenticated by a short-lived token — your API key never leaves your server.

Integration flow

  1. Your backend calls POST /api/v1/embed/sessions with its dfk_ key.
  2. The API returns a signed url (default: 2 hours).
  3. Your front loads the URL into an <iframe> from an origin declared in allowed_domains.
  4. The studio and your page talk through postMessage.

Create the session

curl -X POST "https://dokkraft.blocsland.com/api/v1/embed/sessions" \
  -H "Authorization: Bearer dfk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "template_id": "TEMPLATE_PUBLIC_ID",
    "allowed_domains": ["https://app.your-product.com"],
    "ttl_minutes": 120,
    "permissions": { "variables": "frozen", "ai": false }
  }'

201 response:

{
  "url": "https://dokkraft.blocsland.com/embed/studio/dem_…",
  "token": "dem_…",
  "expires_at": "2026-09-14T12:00:00+00:00",
  "permissions": { "variables": "frozen", "ai": false, "save": true, "export_pdf": true }
}

Permissions

Permission Default Effect
variables frozen Variables frozen (frozen) or editable (editable) in the iframe
ai false AI assistant available
save true Template saving allowed
export_pdf true PDF export allowed

postMessage bridge

Expected message sources: dokkraft-embed (iframe → parent) and dokkraft-host (parent → iframe). Always filter on event.origin.

Direction Type Payload
parent → iframe save {} — triggers saving
parent → iframe generate {} — generates the PDF
parent → iframe ping {} — liveness check
iframe → parent ready {} — studio loaded
iframe → parent dirty { dirty: boolean } (debounced)
iframe → parent saved { templateId, name, created }
iframe → parent generated { dataUrl, filename }
iframe → parent state { dirty, templateId, name, isVariant }
iframe → parent error { code?, added?, removed?, message }
iframe → parent session.revoked { reason: "revoked" } — session revoked in real time (WebSocket)
iframe → parent session.expired { reason: "expired" } — TTL exceeded
The session.revoked and session.expired messages arrive without any action on your side: the session was closed (revocation via DELETE /api/v1/embed/sessions/{token}, TTL or API key expiry). The iframe locks itself — hide your buttons and issue a new session. TTL expiry is tracked by a local timer inside the iframe; DokKraft additionally pushes session.expired over WebSocket when the tab was asleep at TTL time (server-side detection every minute).
// Parent → iframe (origins filtered on both sides)
iframe.contentWindow.postMessage(
  { source: 'dokkraft-host', type: 'save' },
  new URL(iframe.src).origin,
);

// iframe → parent
window.addEventListener('message', (event) => {
  if (event.origin !== expected) return;
  if (event.data?.source !== 'dokkraft-embed') return;
  if (event.data.type === 'generated') download(event.data.dataUrl);
});

Security

  • The dem_… token is short-lived (5 to 1440 minutes) and carries no session.
  • Origins are verified on both sides: never put a wildcard in allowed_domains.
  • A frozen template (variables: frozen) only allows editing the content, not the structure.