Config
The Config API allows you to store and retrieve JSON configuration files at different scopes: organization-wide, repository-wide, or path-specific. Configs support both single-sheet and multi-sheet JSON formats.
Common Use Cases:
- Site-wide settings and metadata
- Access permissions and security policies
- Page-specific configurations
- Feature flags and environment settings
Create or Update Config
POST /config/{org}/{repo}/{path}
Creates a new configuration or updates an existing one. Configs must be valid JSON and follow the single-sheet or multi-sheet format.
Parameters
Headers
https://main--docket--da-pilot.aem.live/fragments/api/headers
Path
org- Organization namerepo- Repository namepath- Config path (e.g.,config,site-config,drafts/page-config)
Body
Content-Type: multipart/form-data
config(required) - JSON string containing the configuration data
Examples
Multi-Sheet Config
- curl (bash)
- Javascript
curl -X POST \
'https://admin.da.live/config/geometrixx/outdoors/config' \
--header 'Authorization: Bearer {IMS_TOKEN}' \
--form 'config={
":names": ["permissions", "settings"],
":type": "multi-sheet",
"permissions": {
"total": 1,
"data": [
{
"path": "CONFIG",
"actions": "write",
"groups": "admins"
}
]
},
"settings": {
"total": 2,
"data": [
{
"key": "site-name",
"value": "Geometrixx Outdoors"
},
{
"key": "theme",
"value": "adventure"
}
]
}
}'
async function createConfig(org, repo, path, configData) {
const formData = new FormData();
formData.append('config', JSON.stringify(configData));
const response = await fetch(
`https://admin.da.live/config/${org}/${repo}/${path}`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${IMS_TOKEN}`
},
body: formData
}
);
if (response.status === 401) {
throw new Error('Authentication failed');
}
if (response.status === 400) {
const error = await response.json();
throw new Error(error.error || 'Invalid config');
}
if (response.status === 201) {
return await response.json();
}
throw new Error(`Unexpected status: ${response.status}`);
}
// Usage - multi-sheet config
const multiSheetConfig = {
":names": ["permissions", "settings"],
":type": "multi-sheet",
"permissions": {
"total": 1,
"data": [
{
"path": "CONFIG",
"actions": "write",
"groups": "admins"
}
]
},
"settings": {
"total": 2,
"data": [
{
"key": "site-name",
"value": "Geometrixx Outdoors"
},
{
"key": "theme",
"value": "adventure"
}
]
}
};
await createConfig('geometrixx', 'outdoors', 'config', multiSheetConfig);
Single-Sheet Config
- curl (bash)
- Javascript
curl -X POST \
'https://admin.da.live/config/geometrixx/outdoors/permissions' \
--header 'Authorization: Bearer {IMS_TOKEN}' \
--form 'config={
":sheetname": "permissions",
":type": "sheet",
"total": 2,
"data": [
{
"path": "CONFIG",
"actions": "write",
"groups": "admins"
},
{
"path": "/drafts",
"actions": "read,write",
"groups": "editors"
}
]
}'
// Usage - single-sheet config
const singleSheetConfig = {
":sheetname": "permissions",
":type": "sheet",
"total": 2,
"data": [
{
"path": "CONFIG",
"actions": "write",
"groups": "admins"
},
{
"path": "/drafts",
"actions": "read,write",
"groups": "editors"
}
]
};
await createConfig('geometrixx', 'outdoors', 'permissions', singleSheetConfig);
Path-Specific Config
- Javascript
// Create config for a specific path or page
const pageConfig = {
":names": ["permissions", "metadata"],
":type": "multi-sheet",
"permissions": {
"total": 1,
"data": [
{
"path": "CONFIG",
"actions": "write",
"groups": "editors"
}
]
},
"metadata": {
"total": 3,
"data": [
{
"property": "title",
"value": "Product Landing Page"
},
{
"property": "template",
"value": "landing"
},
{
"property": "seo-description",
"value": "Discover our latest products"
}
]
}
};
await createConfig('geometrixx', 'outdoors', 'products/landing-page-config', pageConfig);
Response
- 201 (json)
{
":names": ["permissions", "settings"],
":type": "multi-sheet",
"permissions": {
"total": 1,
"data": [
{
"path": "CONFIG",
"actions": "write",
"groups": "admins"
}
]
},
"settings": {
"total": 2,
"data": [
{
"key": "site-name",
"value": "Geometrixx Outdoors"
},
{
"key": "theme",
"value": "adventure"
}
]
}
}
Behavior Notes:
- Returns 201 with the stored config JSON as response body
- POST to existing config path will overwrite (update) the config
- Config is stored immediately in Cloudflare KV
- Response contains the exact JSON that was stored
Permissions Validation:
- If your config includes a
permissionssheet, it MUST have at least one entry withpath: "CONFIG",actions: "write", and a non-emptygroupsvalue - Configs without a permissions sheet are allowed (no validation required)
- This ensures someone with CONFIG write permission can always manage configurations
Error Responses:
- 400 Bad Request - Invalid JSON, missing
configparameter, or permissions validation failed - 401 Unauthorized - Invalid or missing authentication token (empty body)
Get Config
GET /config/{org}/{repo}/{path}
Retrieves a configuration by path.
Parameters
Headers
https://main--docket--da-pilot.aem.live/fragments/api/headers
Path
org- Organization namerepo- Repository namepath- Config path used when creating the config
Examples
Get Config
- curl (bash)
- Javascript
curl -X GET \
'https://admin.da.live/config/geometrixx/outdoors/config' \
--header 'Authorization: Bearer {IMS_TOKEN}'
async function getConfig(org, repo, path) {
const response = await fetch(
`https://admin.da.live/config/${org}/${repo}/${path}`,
{
method: 'GET',
headers: {
'Authorization': `Bearer ${IMS_TOKEN}`,
'Accept': 'application/json'
}
}
);
if (response.status === 401) {
throw new Error('Authentication failed');
}
if (response.status === 404) {
return null; // Config not found
}
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return await response.json();
}
// Usage
const config = await getConfig('geometrixx', 'outdoors', 'config');
if (config) {
// Access multi-sheet config
const siteName = config.settings.data.find(s => s.key === 'site-name')?.value;
console.log(`Site: ${siteName}`);
// Check permissions
const hasConfigWrite = config.permissions.data.some(
p => p.path === 'CONFIG' && p.actions.includes('write')
);
}
// Get path-specific config
const pageConfig = await getConfig('geometrixx', 'outdoors', 'products/landing-page-config');
Response
- 200 (json)
{
":names": ["permissions", "settings"],
":type": "multi-sheet",
"permissions": {
"total": 1,
"data": [
{
"path": "CONFIG",
"actions": "write",
"groups": "admins"
}
]
},
"settings": {
"total": 2,
"data": [
{
"key": "site-name",
"value": "Geometrixx Outdoors"
},
{
"key": "theme",
"value": "adventure"
}
]
}
}
Behavior Notes:
- Returns raw JSON exactly as it was stored
- Case-sensitive path matching
- No automatic inheritance or fallback from parent paths
Error Responses:
- 404 Not Found - Config does not exist at the specified path (returns
{"error": "not found"}) - 401 Unauthorized - Invalid or missing authentication token (empty body)
Config Scopes
Organization and Path Hierarchy
Configs can be created at different levels:
- Javascript
// Organization-level config
// Path: /config/{org}/{repo}/config
await createConfig('geometrixx', 'outdoors', 'config', orgConfig);
// Repository root config
// Path: /config/{org}/{repo}/site-config
await createConfig('geometrixx', 'outdoors', 'site-config', siteConfig);
// Directory-specific config
// Path: /config/{org}/{repo}/drafts/config
await createConfig('geometrixx', 'outdoors', 'drafts/config', draftsConfig);
// Page-specific config
// Path: /config/{org}/{repo}/products/landing-page-config
await createConfig('geometrixx', 'outdoors', 'products/landing-page-config', pageConfig);
Important: There is no automatic inheritance or cascade. Each config path is independent. To implement config inheritance, you must manually fetch and merge configs from different scopes in your application logic.
JSON Format Specifications
Multi-Sheet Format
Use for configs with multiple related data sets (permissions, settings, metadata, etc.):
- json
{
":names": ["sheet1", "sheet2", "sheet3"],
":type": "multi-sheet",
"sheet1": {
"total": 2,
"data": [
{ "key": "value" }
]
},
"sheet2": {
"total": 1,
"data": [
{ "key": "value" }
]
}
}
Required fields:
:names- Array of sheet names:type- Must be "multi-sheet"- Each sheet must have
totalanddataproperties
Single-Sheet Format
Use for simple configs with one data set:
- json
{
":sheetname": "permissions",
":type": "sheet",
"total": 2,
"data": [
{ "key": "value" }
]
}
Required fields:
:sheetname- Name of the sheet:type- Must be "sheet"total- Number of data rowsdata- Array of objects
Common Patterns
Site Configuration with Permissions
- Javascript
const siteConfig = {
":names": ["permissions", "site", "seo"],
":type": "multi-sheet",
"permissions": {
"total": 3,
"data": [
{ "path": "CONFIG", "actions": "write", "groups": "admins" },
{ "path": "/drafts", "actions": "read,write", "groups": "editors" },
{ "path": "/", "actions": "read", "groups": "public" }
]
},
"site": {
"total": 5,
"data": [
{ "key": "name", "value": "Geometrixx Outdoors" },
{ "key": "domain", "value": "outdoors.geometrixx.com" },
{ "key": "language", "value": "en" },
{ "key": "timezone", "value": "America/Los_Angeles" },
{ "key": "env", "value": "production" }
]
},
"seo": {
"total": 3,
"data": [
{ "key": "title", "value": "Geometrixx Outdoors - Adventure Gear" },
{ "key": "description", "value": "Premium outdoor equipment and apparel" },
{ "key": "keywords", "value": "outdoor, camping, hiking, adventure" }
]
}
};
await createConfig('geometrixx', 'outdoors', 'config', siteConfig);
Update Config (Merge Pattern)
- Javascript
async function updateConfigSheet(org, repo, path, sheetName, newData) {
// 1. Get existing config
const config = await getConfig(org, repo, path);
if (!config) {
throw new Error('Config not found');
}
// 2. Update specific sheet
if (config[sheetName]) {
// Merge or replace data
config[sheetName].data = newData;
config[sheetName].total = newData.length;
} else {
// Add new sheet
config[sheetName] = {
total: newData.length,
data: newData
};
config[':names'].push(sheetName);
}
// 3. Save updated config
return await createConfig(org, repo, path, config);
}
// Usage
await updateConfigSheet('geometrixx', 'outdoors', 'config', 'settings', [
{ "key": "theme", "value": "light" },
{ "key": "new-feature", "value": "enabled" }
]);
Best Practices
- Always include CONFIG permission - If your config has a permissions sheet, always include an entry for CONFIG write access
- Use consistent naming - Adopt a naming convention for config paths (e.g.,
configfor org-level,{path}-configfor path-specific) - Validate before saving - Parse and validate JSON structure in your application before sending to the API
- Version your configs - Consider storing config backups or using version control patterns
- Separate concerns - Use different sheets for different types of configuration (permissions, settings, metadata)
- Document your schemas - Maintain documentation of expected fields and values for each config type