Skip to main content

POST /api/powerpoint/generate

Generates a complete PowerPoint presentation server-side and returns it as base64. Supports five typed slide layouts with consistent theming, footers, tables, two-column layouts, and bullet lists.

Base URL: https://app.keelstone.dev
Authentication: Authorization: Bearer <keelstoneSessionId>
Plan: Pro


Request

POST /api/powerpoint/generate
Content-Type: application/json
Authorization: Bearer <keelstoneSessionId>
{
slides: Slide[]; // Array of slide definitions (see below)
title?: string; // Presentation title (metadata only)
footer?: string; // Footer text shown on every slide
theme?: ThemeOverride; // Optional colour overrides
}

Slide types

Every slide object requires a type field. The remaining fields depend on the type.


cover

Full-bleed title slide with a dark background.

{
type: 'cover';
title: string; // Large headline
subtitle?: string; // Smaller text below the divider
meta?: string; // Small line below subtitle (e.g. date, author)
}

bullets

Slide with a header, optional callout bar, body text, bullet list, and numbered steps.

{
type: 'bullets';
title: string;
callout?: string; // Highlighted bar below the header
body?: string; // Paragraph text
bullets?: string[]; // Bullet list items
steps?: string[]; // Numbered list items (rendered below bullets)
}

two-column

Two side-by-side columns, each with a coloured header bar and content box.

{
type: 'two-column';
title: string;
left: {
heading: string;
bullets?: string[];
body?: string;
};
right: {
heading: string;
bullets?: string[];
body?: string;
};
callout?: string; // Full-width bar at the bottom of the slide
}

table

Slide with a styled data table. The header row uses the primary theme colour; rows alternate between white and a light tint.

{
type: 'table';
title: string;
headers: string[]; // Column header labels
rows: string[][]; // Data rows — each inner array must match headers.length
}

agenda

Numbered agenda items laid out in a grid with coloured badge circles.

{
type: 'agenda';
title: string;
items: {
title: string;
description?: string;
}[];
}

Theme overrides

All colours are six-digit hex strings without the # prefix.

{
primary?: string; // Default: '032D60' (Salesforce navy)
accent?: string; // Default: '0176D3' (Salesforce blue)
accentAlt?: string; // Default: '00A1E0'
light?: string; // Default: 'EEF4FF'
text?: string; // Default: '1A1A1A'
textMuted?: string; // Default: '5A5A5A'
white?: string; // Default: 'FFFFFF'
footerBg?: string; // Default: '032D60'
}

Response

200 OK

{ "base64": "<base64-encoded .pptx file>" }

400 Bad Request — missing or invalid slides array

500 Internal Server Error — generation failed


Example — full presentation

import { KSPowerPoint } from 'kstone/api';

export default class QuarterlyReview extends KSPowerPoint {
@api keelstoneSessionId;

async handleGenerate() {
await this.ksGeneratePresentation(
[
{
type: 'cover',
title: 'Q3 Pipeline Review',
subtitle: 'Sales Operations',
meta: 'October 2025',
},
{
type: 'agenda',
title: 'Agenda',
items: [
{ title: 'Pipeline Summary', description: 'By region and stage' },
{ title: 'Top Opportunities', description: 'Over $500K' },
{ title: 'Forecast', description: 'Q3 vs Q4 projection' },
],
},
{
type: 'table',
title: 'Open Opportunities by Stage',
headers: ['Stage', 'Count', 'Total ACV', 'Avg Deal Size'],
rows: [
['Prospecting', '14', '$420,000', '$30,000'],
['Qualification', '9', '$810,000', '$90,000'],
['Proposal', '6', '$1,200,000', '$200,000'],
['Negotiation', '3', '$900,000', '$300,000'],
],
},
{
type: 'two-column',
title: 'Regional Breakdown',
left: {
heading: 'North America',
bullets: ['$2.1M total pipeline', '18 active deals', 'Q3 close rate: 34%'],
},
right: {
heading: 'EMEA',
bullets: ['$980K total pipeline', '9 active deals', 'Q3 close rate: 28%'],
},
callout: 'North America leads on volume; EMEA leads on average deal size.',
},
{
type: 'bullets',
title: 'Key Actions',
callout: 'Focus for the next 30 days',
bullets: [
'Accelerate 6 Negotiation-stage deals before quarter end',
'Schedule exec sponsor calls for top 3 EMEA opportunities',
],
steps: [
'Update close dates in Salesforce by Oct 10',
'Submit forecast adjustments to RevOps by Oct 15',
'Present final pipeline to leadership on Oct 20',
],
},
],
{
footer: 'Keelstone Sales Operations — Confidential',
theme: { primary: '032D60', accent: '0176D3' },
}
);
}
}

Calling from Apex

String keelstoneSessionId = '...'; // from flow or LWC input

List<Map<String, Object>> slides = new List<Map<String, Object>>{
new Map<String, Object>{
'type' => 'cover',
'title' => 'Account Review: Acme Corp',
'subtitle' => 'Prepared by Sales Operations',
'meta' => String.valueOf(Date.today())
},
new Map<String, Object>{
'type' => 'table',
'title' => 'Open Opportunities',
'headers' => new List<String>{ 'Name', 'Stage', 'Close Date', 'Amount' },
'rows' => myRows // List<List<String>> built from SOQL results
}
};

Map<String, Object> body = new Map<String, Object>{
'slides' => slides,
'footer' => 'Acme Corp — Confidential'
};

HttpRequest req = new HttpRequest();
req.setEndpoint('https://app.keelstone.dev/api/powerpoint/generate');
req.setMethod('POST');
req.setHeader('Content-Type', 'application/json');
req.setHeader('Authorization', 'Bearer ' + keelstoneSessionId);
req.setBody(JSON.serialize(body));
req.setTimeout(30000);

HttpResponse res = new Http().send(req);
Map<String, Object> result = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
String pptxBase64 = (String) result.get('base64');

Pass pptxBase64 to KS_InsertAtCursor or another invocable action to insert the file into the open PowerPoint document.


Tips

  • Slide order matters — slides render in array order. Always start with a cover for polished output.
  • Footer — set once at the request level; it appears on every slide automatically. Omit it if you don't want a footer.
  • Tables — all cells are strings. Format numbers and dates before passing them in (e.g. '$1,200,000' not 1200000).
  • Two-column callout — the callout bar spans the full slide width and uses the accent colour. Use it for a single key insight that bridges both columns.
  • Theme — if you leave theme out, the Keelstone default (Salesforce colour palette) is used. Override only the colours you need.