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
}
| Field | Type | Required | Description |
|---|---|---|---|
templateBase64 | string | Yes (xlsx/docx) | The template encoded as base64. Fetch from Salesforce Files using ExcelTemplateController.getTemplate() or WordTemplateController.getTemplate() |
data | object | Yes | Merge context. For doc_type: 'pdf', this is a pdfmake docDefinition object. |
doc_type | string | No | Output format. Default: 'excel' |
sheetNumber | number | No | Which sheet to apply substitution on (xlsx only). Defaults to 1 |
linkedSharePointPath | string | No | SharePoint folder path to upload the result into. Requires Pro plan and SharePoint configured in Setup. |
filename | string | No | Output 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 Forbidden — linkedSharePointPath 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.