Skip to main content

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
}
FieldTypeRequiredDescription
templateBase64stringYesThe Excel template encoded as base64. Fetch this from Salesforce Files using ExcelTemplateController.getTemplate()
dataobjectYesMerge context. Nested objects and arrays are supported. See Template Variables
sheetNumbernumberNoWhich 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.