Skip to main content

POST /api/docs/generate

Merges data into a template and returns the result as base64. Supports Excel (.xlsx), Word (.docx), and PDF output.

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

Request

POST /api/docs/generate
Content-Type: application/json
Authorization: Bearer <keelstoneSessionId>
{
templateBase64?: string; // Base64-encoded template file (.xlsx or .docx)
data: object; // Merge data — must match the template's placeholders
doc_type?: string; // 'excel' (default) | 'word' | 'pdf'
sheetNumber?: number; // Sheet index (1-based, xlsx only). Default: 1
linkedSharePointPath?: string; // SharePoint folder to upload the result into (Pro+)
filename?: string; // Output filename — used as the SharePoint filename
}
FieldTypeRequiredDescription
templateBase64stringYes (xlsx/docx)The template encoded as base64. Fetch from Salesforce Files using ExcelTemplateController.getTemplate() or WordTemplateController.getTemplate()
dataobjectYesMerge context. For doc_type: 'pdf', this is a pdfmake docDefinition object.
doc_typestringNoOutput format. Default: 'excel'
sheetNumbernumberNoWhich sheet to apply substitution on (xlsx only). Defaults to 1
linkedSharePointPathstringNoSharePoint folder path to upload the result into. Requires Pro plan and SharePoint configured in Setup.
filenamestringNoOutput filename. Used as the SharePoint filename when linkedSharePointPath is set.

Response

200 OK

{
"base64": "<base64-encoded merged file>",
"sharePointFileUrl": "https://contoso.sharepoint.com/..."
}

sharePointFileUrl is only present when linkedSharePointPath was supplied and the SharePoint upload succeeded.

The MIME type of the returned file depends on doc_type:

  • 'excel'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
  • 'word'application/vnd.openxmlformats-officedocument.wordprocessingml.document
  • 'pdf'application/pdf

400 Bad Request — missing required fields

{ "error": "templateBase64 and data are required" }

403 ForbiddenlinkedSharePointPath was supplied but the org is not on Pro

{ "error": "SharePoint integration requires the Keelstone Pro plan or higher." }

500 Internal Server Error — merge failed

{ "error": "Failed to generate document" }

Excel example (LWC)

import getTemplate from '@salesforce/apex/ExcelTemplateController.getTemplate';

async function generateReport(templateId, mergeData) {
const templateBase64 = await getTemplate({ contentDocumentId: templateId });

const response = await fetch('https://app.keelstone.dev/api/docs/generate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.keelstoneSessionId}`
},
body: JSON.stringify({
templateBase64,
data: mergeData,
doc_type: 'excel'
})
});

const { base64 } = await response.json();
return base64;
}

Or using ksCall() from KSExcel:

const { base64 } = await this.ksCall('/api/docs/generate', {
templateBase64,
data: mergeData,
});
await this.ksInsert(base64, 'AccountReport.xlsx');

Word example (LWC)

KSWord.ksGenerate() handles this call automatically:

import { KSWord } from 'kstone/api';
import getTemplate from '@salesforce/apex/WordTemplateController.getTemplate';

export default class MyDoc extends KSWord {
@api keelstoneSessionId;

async handleGenerate() {
const templateBase64 = await getTemplate({ contentDocumentId: this.templateId });
await this.ksGenerate(templateBase64, { account: this.account }, 'Contract.docx');
}
}

PDF example (LWC)

import { KSPDF } from 'kstone/api';

export default class MyPdfReport extends KSPDF {
@api keelstoneSessionId;

async handleGenerate() {
const base64 = await this.ksGenerate({
content: [
{ text: 'Account Report', style: 'header' },
{ text: this.accountName }
],
styles: { header: { fontSize: 18, bold: true } }
});
// base64 is a PDF — download or insert as needed
}
}

Template variable syntax (Excel/Word)

The data object maps directly to placeholder syntax in the template file:

// data object
{
account: { Name: "Acme Corp", BillingCity: "San Francisco" },
contacts: [
{ FirstName: "John", LastName: "Doe", Email: "john@acme.com" }
],
reportDate: "January 15, 2024"
}
// Excel template cells / Word template tags
{account.Name} → "Acme Corp"
{account.BillingCity} → "San Francisco"
{reportDate} → "January 15, 2024"

// Table rows (repeated for each contact)
{#contacts}{FirstName} {LastName}{/contacts}

See Template Variables for the complete syntax reference.

Calling from Apex (server-to-server)

HttpRequest req = new HttpRequest();
req.setEndpoint('https://app.keelstone.dev/api/docs/generate');
req.setMethod('POST');
req.setHeader('Content-Type', 'application/json');
req.setHeader('Authorization', 'Bearer ' + keelstoneSessionId);

Map<String, Object> body = new Map<String, Object>{
'templateBase64' => templateBase64,
'data' => mergeDataMap,
'doc_type' => 'excel'
};
req.setBody(JSON.serialize(body));

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

Add https://app.keelstone.dev to your org's Remote Site Settings before making callouts.


Looking for template-key-based generation without handling template base64 yourself? See POST /api/docs/generate-from-key, which resolves the template from Salesforce automatically and accepts any JSON merge context.

Need to generate many documents in one call from an Apex batch class? See POST /api/docs/generate-bulk, which merges N documents server-side and uploads all results to Salesforce in a single request.

Want to use a template stored in SharePoint, or save results to SharePoint? See the SharePoint Integration page.