Storage Providers
How to configure REFRACT PDF's storage system. Covers SharePoint setup, Azure Blob Storage setup, output routing via storage-config.json, required environment variables, and the response headers returned on each render.
Overview
REFRACT PDF uses two storage providers. You configure which one handles each output library using storage-config.json.
| Provider | Role |
|---|---|
| SharePoint | Always active. REFRACT PDF reads all templates, payloads, configurations, and assets from your SharePoint site. SharePoint can also receive generated PDFs, reports, and archive files. |
| Azure Blob Storage | Optional. Route any output library (generated documents, reports, archive, audit logs) to an Azure Storage account instead of SharePoint. |
SharePoint is always required. Azure Blob Storage is provisioned only when you route at least one output library to blob in your storage-config.json.
Step 1 -- Configure SharePoint
sp-config.json
REFRACT PDF needs the SharePoint site and library identifiers for your tenant. Provide these in sp-config.json, which is deployed alongside the REFRACT PDF service.
{
"siteId": "contoso.sharepoint.com,<site-guid>,<web-guid>",
"driveIds": {
"Templates": "<drive-id>",
"System Templates": "<drive-id>",
"Configurations": "<drive-id>",
"Payloads": "<drive-id>",
"Generated Documents": "<drive-id>",
"Reports": "<drive-id>",
"Archive": "<drive-id>",
"Audit Logs": "<drive-id>"
},
"lists": {
"VAULTPDF_Activity": "<list-id>"
},
"features": {
"generatedDocuments": true,
"reports": true,
"archive": true,
"auditLogs": true
}
}How to find your IDs:
| Value | How to retrieve |
|---|---|
siteId | Call GET https://graph.microsoft.com/v1.0/sites/{hostname}:{path} and copy the id field |
driveIds | Call GET https://graph.microsoft.com/v1.0/sites/{siteId}/drives and match each library by name |
VAULTPDF_Activity list ID | Call GET https://graph.microsoft.com/v1.0/sites/{siteId}/lists and match by displayName |
Feature flags
The features object controls which output libraries are active. Set a flag to false to silently skip writes to that library.
| Flag | Effect when false |
|---|---|
features.generatedDocuments | Generated PDFs are not uploaded to SharePoint |
features.reports | Error and scheduled reports are not uploaded |
features.archive | Archive writes are skipped |
features.auditLogs | Audit JSONL writes to SharePoint are skipped |
When a library is routed to Azure Blob in storage-config.json, REFRACT PDF automatically treats its feature flag as enabled -- you do not need to set it to true in sp-config.json.
SP_SECRETS environment variable
The SharePoint credentials are provided as a JSON string in the SP_SECRETS environment variable. Set this in your production app settings, backed by a Key Vault reference.
{
"tenantId": "<azure-ad-tenant-id>",
"clientId": "<app-registration-client-id>",
"clientSecret": "<secret>"
}The app registration must have the following Microsoft Graph application permissions on your SharePoint site:
Sites.ReadWrite.All(or site-scopedSites.Selected)Files.ReadWrite.All
Step 2 -- Choose Output Storage
By default, all generated documents are written back to SharePoint. If you want some or all output libraries routed to Azure Blob Storage instead, follow the steps below.
SharePoint only (default)
No additional configuration needed. Omit STORAGE_CONFIG_PATH from your app settings, or create a storage-config.json with all routes set to sharepoint:
{
"libraryRoutes": {
"generatedDocuments": "sharepoint",
"reports": "sharepoint",
"archive": "sharepoint",
"auditLogs": "basic"
},
"accountName": "",
"blobContainers": {}
}Azure Blob Storage (optional)
To route one or more output libraries to Azure Blob:
- Create an Azure Storage account (general-purpose v2 or later).
- Create a container for each library you want to route to Blob (e.g.
generated-documents,document-archive). - Assign the Storage Blob Data Contributor role to the REFRACT PDF app's Managed Identity on the storage account.
- Set
STORAGE_CONFIG_PATHin your app settings to the path of yourstorage-config.jsonfile. - Configure
storage-config.jsonas described in the next section.
Blob naming convention
Files written to Azure Blob follow this path pattern:
{DocType}/{YYYY}/{MM}/{correlationId}_{fileName}.pdfExamples:
Invoice/2026/03/BC-INV-001_Invoice_2026-03-31.pdf
Reports/RenderErrors/2026/03/abc-123_error_REFRACT PDF.pdf
document-archive/2026/01/abc-100_SO-00400-Invoice.pdfSAS URLs
After every upload to Blob, REFRACT PDF generates a time-limited SAS URL. The expiry window is set by sasUrlExpiryDays in storage-config.json (default: 30 days, max recommended: 180 days). The SAS URL is returned in the X-REFRACTPDF-BlobSasUrl response header and stored in the Activity list item so users can open the document directly from SharePoint.
storage-config.json
storage-config.json controls which output libraries go to SharePoint and which go to Azure Blob. Deploy this file alongside the REFRACT PDF service and set STORAGE_CONFIG_PATH to its path.
Full schema
{
"libraryRoutes": {
"generatedDocuments": "sharepoint | blob",
"reports": "sharepoint | blob",
"archive": "sharepoint | blob",
"auditLogs": "basic | blob | enterprise"
},
"accountName": "your-storage-account-name",
"blobContainers": {
"generatedDocuments": "generated-documents",
"reports": "reports",
"archive": "document-archive",
"auditLogs": "audit-logs"
},
"sasUrlExpiryDays": 30
}Field reference
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
libraryRoutes | object | Yes | -- | Per-library routing declarations |
accountName | string | When any route is blob | -- | Azure Storage account name |
blobContainers | object | When any route is blob | -- | Library to container name map |
sasUrlExpiryDays | number | No | 30 | Days until generated SAS URLs expire. Max recommended: 180. |
libraryRoutes valid values
| Library | Valid values | Default |
|---|---|---|
generatedDocuments | 'sharepoint' | 'blob' | 'sharepoint' |
reports | 'sharepoint' | 'blob' | 'sharepoint' |
archive | 'sharepoint' | 'blob' | 'sharepoint' |
auditLogs | 'basic' | 'blob' | 'enterprise' | 'basic' |
Libraries omitted from libraryRoutes fall back to their defaults. If STORAGE_CONFIG_PATH is not set at all, every library defaults to SharePoint.
Example: Reports on SharePoint, everything else on Blob
A common production configuration -- reports stay in SharePoint so users can browse them, generated documents and archive go to Blob for cost efficiency:
{
"libraryRoutes": {
"generatedDocuments": "blob",
"reports": "sharepoint",
"archive": "blob",
"auditLogs": "enterprise"
},
"accountName": "REFRACT PDFstorage",
"blobContainers": {
"generatedDocuments": "generated-documents",
"archive": "document-archive",
"auditLogs": "audit-logs"
},
"sasUrlExpiryDays": 90
}Example: SharePoint only
{
"libraryRoutes": {
"generatedDocuments": "sharepoint",
"reports": "sharepoint",
"archive": "sharepoint",
"auditLogs": "basic"
},
"accountName": "",
"blobContainers": {}
}Environment Variables
Set these in your production app settings. Use Key Vault references for all secrets.
| Variable | Required | Description |
|---|---|---|
SP_CONFIG_PATH | Yes | Absolute path to sp-config.json on the deployment filesystem |
SP_SECRETS | Yes | JSON string with tenantId, clientId, clientSecret for SharePoint access |
STORAGE_CONFIG_PATH | No | Absolute path to storage-config.json. When absent, all output routes default to SharePoint. |
AUDIT_SERVICEBUS_CONNECTION_STRING | When auditLogs: enterprise | Service Bus connection string with Send rights. Use a Key Vault reference. |
Response Headers
REFRACT PDF sets the following headers on every successful render response. Which headers are present depends on your libraryRoutes configuration.
| Header | Present when | Value |
|---|---|---|
X-REFRACTPDF-UploadStatus | Always | ok, failed, or skipped |
X-REFRACTPDF-UploadError | Upload failed or skipped | Error message (newlines stripped, max 512 chars) |
X-REFRACTPDF-WebUrl | generatedDocuments: sharepoint | SharePoint item web URL |
X-REFRACTPDF-DriveItemId | generatedDocuments: sharepoint | SharePoint DriveItem ID |
X-REFRACTPDF-BlobUrl | generatedDocuments: blob | Raw Blob URL |
X-REFRACTPDF-BlobSasUrl | generatedDocuments: blob | Time-limited SAS URL (browser-accessible) |
X-REFRACTPDF-AuditStatus | Audit write skipped or failed | skipped:reason or failed:message |
Your calling application should handle both X-REFRACTPDF-WebUrl and X-REFRACTPDF-BlobSasUrl -- the header that appears depends on your routing configuration.
Related Pages
- Audit Logs -- choose and configure an audit tier (basic, blob, enterprise)
- System Architecture -- how REFRACT PDF fits into your tenant
Relay Mode
How to trigger asynchronous, queue-based rendering for a single document via options.features.relay, how the request is routed through Service Bus, and how to confirm after the fact whether a render was queued or returned inline.
Audit Logs
How to configure REFRACT PDF's audit system. Covers all three audit tiers -- basic (SharePoint JSONL), blob (Azure Blob AppendBlob), and enterprise (Service Bus + Audit Worker) -- including the AuditEvent schema, file naming, and setup steps for each tier.