POST /api/docs/generate
Merges data into an Excel template and returns the result as base64. This endpoint is called directly from LWC components — no Keelstone session is required.
Base URL: https://app.keelstone.dev
Authentication: None
Request
POST /api/docs/generate
Content-Type: application/json
{
templateBase64: string; // Base64-encoded .xlsx template file
data: object; // Merge data — must match the template's placeholders
sheetNumber?: number; // Sheet index (1-based). Default: 1
}
| Field | Type | Required | Description |
|---|---|---|---|
templateBase64 | string | Yes | The Excel template encoded as base64. Fetch this from Salesforce Files using ExcelTemplateController.getTemplate() |
data | object | Yes | Merge context. Nested objects and arrays are supported. See Template Variables |
sheetNumber | number | No | Which sheet to apply substitution on. Defaults to 1 (first sheet) |
Response
200 OK
{
"base64": "<base64-encoded merged .xlsx>"
}
400 Bad Request — missing required fields
{
"error": "templateBase64 and data are required"
}
500 Internal Server Error — merge failed
{
"error": "Failed to generate document"
}
Example
// In your LWC
import getTemplate from '@salesforce/apex/ExcelTemplateController.getTemplate';
async function generateReport(templateId, mergeData) {
// 1. Fetch template bytes from Salesforce Files
const templateBase64 = await getTemplate({ contentDocumentId: templateId });
// 2. Merge
const response = await fetch('https://app.keelstone.dev/api/docs/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
templateBase64,
data: mergeData // plain object, not a JSON string
})
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(error);
}
const { base64 } = await response.json();
return base64;
}
Template variable syntax
The data object maps directly to xlsx-template placeholder syntax in the Excel file:
// data object
{
account: { Name: "Acme Corp", BillingCity: "San Francisco" },
contacts: [
{ FirstName: "John", LastName: "Doe", Email: "john@acme.com" }
],
reportDate: "January 15, 2024"
}
// Corresponding Excel cells
{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)
If you need to generate documents from an Apex context (e.g., a trigger or batch job), call this endpoint via Http:
HttpRequest req = new HttpRequest();
req.setEndpoint('https://app.keelstone.dev/api/docs/generate');
req.setMethod('POST');
req.setHeader('Content-Type', 'application/json');
Map<String, Object> body = new Map<String, Object>{
'templateBase64' => templateBase64,
'data' => mergeDataMap
};
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.