Contentdrips Embed SDK
Integrate powerful content creation directly into your application. Design templates, manage branding, and export graphics — all from your own UI.
What's new in v3
- Plan strings — use
plan: "free" | "starter" | "pro"ininit()andopen(); each maps to the matching Contentdrips plan for that user. - Template gallery —
contentdrips.templates.list(),.categories()for browsable templates with filters and pagination. - Collections —
templates.collections()for dashboard-curated template groups (Starter/Pro embed subscription). - My Designs —
templates.myDesigns()for saved designs per embed user (keyed onemail/user_id; Starter/Pro). - Structure —
templates.getStructure(id)to discovercontent_updatelabels before automation. - Content fills —
content_update,carousel(intro / slides / ending), andbrandingonopen(). contentdrips.destroy()for full teardown when unmounting the host page.
Try the Integration
Integration Guide
1. Include the SDK
Load the Contentdrips embed script once in your app:
<!-- Add before closing </body> tag -->
<script src="https://assets.contentdrips.com/embed.js"></script>2. Initialize the SDK
Call init before any other method. Set a default end-user tier with plan: "free", "starter", or "pro" — maps to the corresponding Contentdrips plan. You can override it on any open() call.
await contentdrips.init({
client_id: "your_client_id",
email: "user@example.com",
user_id: "unique_user_123",
environment: "production",
plan: "starter"
});Alternatively pass user_package instead of plan if your stack uses numeric codes; values map to the same Contentdrips plans.
3. Set User Profile (Optional)
Pre-populate templates with user data:
contentdrips.profile.set({
name: "John Doe",
handle: "@johndoe",
avatar: "https://example.com/avatar.jpg",
website: "https://johndoe.com",
bio: "Software Developer"
});4. Open the Editor
Launch the modal with defaults, a template, scratch canvas, image, plan override, pre-filled content, or carousel. If you pass both plan and user_package on open(), plan wins.
contentdrips.open();
contentdrips.open({ template: 126133 });
contentdrips.open({ plan: "pro" });
contentdrips.open({
image: "https://example.com/photo.jpg"
});
contentdrips.open({
is_scratch: true,
canvas_width: 1080,
canvas_height: 1080
});
// Pre-fill text fields (labels must match template meta)
contentdrips.open({
template: 126133,
content_update: [
{ type: "textbox", label: "heading", value: "Hello" },
],
branding: {
name: "Jane",
avatar_image_url: "https://example.com/a.jpg"
}
});
// Pre-fill carousel (intro, slides, ending)
contentdrips.open({
template: 126133,
carousel: {
intro_slide: { heading: "Title", description: "Sub" },
slides: [{ heading: "Slide 1", description: "..." }],
ending_slide: { heading: "Thanks" }
},
});
contentdrips.open({ addWatermark: true }); 5. Handle Exported Content
Subscribe after init. Payloads include image URL strings (often data URLs). The modal closes after export by default.
contentdrips.on("image_export", function(data) {
const imageUrl = data.image_url;
});
contentdrips.on("carousel_export", function(data) {
const images = data.images;
});
contentdrips.close();
contentdrips.off("image_export", handler);
contentdrips.destroy();6. Browse Templates (gallery)
Requires successful init. Filter by type, category_id, pagination, or search. The React and Vue examples render a clickable thumbnail grid — clicking any card opens the editor.
const cats = await contentdrips.templates.categories();
const result = await contentdrips.templates.list({
type: "carousel", page: 1, per_page: 12
});
contentdrips.open({ template: result.data[0].id });7. My Designs (Starter/Pro embed plan)
Lists designs saved for the current embed user (keyed on email / user_id from init). Clicking a card re-opens that design in the editor.
const result = await contentdrips.templates.myDesigns({ page: 1 });
// result.data — array of design objects; result.last_page for pagination
contentdrips.open({ template: result.data[0].id });8. Template Structure (getStructure)
Before you automate content fills from a CMS, form, or AI, call getStructure to discover what labels and field types a template exposes. The response tells you exactly which content_update entries to send and whether the template supports carousel slides.
https://api.contentdrips.com/api/embed/template-structure/{templateId}| Parameter | Location | Required | Description |
|---|---|---|---|
templateId | URL path | Yes | Numeric ID of the template |
Example response
{
"template_id": 155034,
"name": "Retor",
"type": "carousel",
"width": 3240,
"height": 1350,
"carousel": {
"intro_slide": { "heading": "Three ways to grow your personal brand", "description": "", "image": "" },
"slides": [
{ "heading": "", "description": "Craft your unique identity…", "image": "" }
],
"ending_slide": { "heading": "Share your thoughts in comments below", "description": "", "image": "" }
},
"content_update": [],
"branding": {
"name": "Usama Khalid",
"handle": "@im.usamakhalid",
"bio": "",
"website_url": "",
"avatar_image_url": "https://cdn.contentdrips.com/avatar.webp"
}
}Mapping the response to open() payloads
The carousel field shows the template's existing slide structure (intro, body slides, ending) — use it as a guide to build your own payload. For image/single-slide templates, content_update contains label objects you fill with your values. The branding field reflects the template's default branding, which you can override in open().
// Flat response — no .data wrapper
const structure = await contentdrips.templates.getStructure(155034);
const { type, carousel, content_update, branding } = structure;
// Carousel template — pass carousel object directly
if (type === "carousel") {
contentdrips.open(({
template: 155034,
carousel: {
intro_slide: { heading: "My Custom Title", description: "", image: "" },
slides: carousel.slides.map((_, i) => (({ heading: `Point ${i + 1}`, description: "", image: "" }))),
ending_slide: carousel.ending_slide,
},
branding: { ...branding, name: "Your Name" },
});
} else {
// Image / single template — use content_update labels
contentdrips.open(({
template: 155034,
content_update: content_update.map((f) => (({ type: f.type, label: f.label, value: cms.get(f.label) })),
});
}Key rules when using getStructure
- Check
typefirst: if it is"carousel", use thecarouselfield to build your slides; otherwise usecontent_updatelabels. You can also use both at the same time. - The
carouselfield contains the template's existing slide content — treat it as a scaffold and replace the values with your own data. - The
brandingfield returns the template's default branding — spread it and override only the fields you need. - Call
getStructureonce per template, cache the result — it does not change between sessions.
9. Collections (Starter/Pro embed plan)
Groups of templates you curate in the Contentdrips embed dashboard. Render each collection as a labelled section of thumbnail cards.
const result = await contentdrips.templates.collections();
result.data.forEach((col) => {
col.templates?.forEach((t) => {
// render t.thumbnail; on click:
contentdrips.open({ template: t.id });
});
});Plans & Subscription
End-user plan (your customers)
Pass plan so your product tiers stay readable. "free", "starter", and "pro" each map to the matching Contentdrips plan for that user (Free, Starter, or Pro on the Contentdrips side).
Your Contentdrips Embed subscription (your company)
This is what you purchase for the integration (MAU, APIs). It is separate from the per-user plan above. Free tier embed typically has no gallery/collections/My Designs APIs; Starter/Pro unlock those. Confirm pricing and limits in your dashboard and contract.
Errors
If your embed account cannot use tier overrides or watermarks, validation may return PRO_PLAN_REQUIRED. The SDK may throw ContentdripsError with that code — prompt an upgrade or remove the option.
Backend endpoints (reference)
Production API base: https://api.contentdrips.com. Examples: GET /api/validate-client; GET /api/embed/templates, /categories, /collections, /my-designs; GET /api/embed/template-structure/{id} (no auth required). Exact query params match your deployed API.
API Reference — core
contentdrips.init(options)Initialize the SDK. Must be called before any other method. Returns a Promise in v3 — use await.
Options: client_id, email (required), user_id, environment, plan ("free" | "starter" | "pro") or user_package (0 | 1 | 4)
contentdrips.profile.set(profileData)Default profile for the editor and template personalization.
name, handle, avatar, website, bio
contentdrips.open(options?)Open the editor modal. See Open Options Reference below.
contentdrips.close()Close the modal programmatically.
contentdrips.on(event, handler) / offimage_export, carousel_export, and other SDK events.
contentdrips.destroy()Remove embed UI and listeners (e.g. on SPA unmount).
Template APIs (async; require init)
contentdrips.templates.list({ ... })Paginated templates — type, category_id, page, per_page, search.
contentdrips.templates.categories()Category list for filters or tabs.
contentdrips.templates.collections()Dashboard collections (Starter/Pro embed subscription).
contentdrips.templates.getStructure(templateId)Structure for prefill and automation.
contentdrips.templates.myDesigns({ page })Saved designs for the embed user (Starter/Pro embed subscription).
Open Options Reference
templateNumeric template idimageHTTPS URL or data URL to editis_scratchBlank canvas (boolean)canvas_width / canvas_heightScratch size in pixelsplan"free" | "starter" | "pro" for this session — wins over user_package if both are setuser_packageUse instead of plan if your stack uses numeric codes; maps to Contentdrips plans. Tier overrides may require a sufficient Contentdrips Embed subscription (PRO_PLAN_REQUIRED otherwise).addWatermarkWatermark on exports when allowed on your embed plancontent_updateArray of { type: "textbox" | "image", label, value } — labels must match template meta_labelscarousel{ intro_slide, slides[], ending_slide } — slides support heading, description, optional image URLbrandingname, handle, avatar_image_url, optional bio, website_urlExport Event Data Structure
image_export event:
{
event: "image_export",
image_url: "data:image/png;base64,..."
}carousel_export event:
{
event: "carousel_export",
images: [
"data:image/png;base64,...",
"data:image/png;base64,...",
...
]
}© 2026 Contentdrips. All rights reserved.