@axeptio/provisioning
v1.1.0
Published
Axeptio provisioning client with state management and batch operations
Readme
@axeptio/provisioning
TypeScript toolkit for automated provisioning of Axeptio entities. It provides a typed HTTP client, composable provisioners, checkpointed execution, and a CLI — optimized for both humans and AI agents.
Why this package
- ✅ Type-safe client with retries and rate limiting
- ✅ Composable provisioners for org → projects → configurations → users
- ✅ Checkpointed execution with resume and rollback
- ✅ Parallel batches with pause/resume
- ✅ Built-in callbacks (publish, scan, logs)
- ✅ CLI and programmatic APIs
- ✅ AI-friendly: small, copy-pasteable recipes and clear method names
Table of Contents
- Quick Start
- Post-Provisioning Callbacks
- Entity Recipes (copy-paste)
- Organizations & Projects
- Projects Groups
- Cookies Configuration
- Project Design & Stylesheet
- Terms (ContractsV2) Configuration
- Vendors (Company & Solution)
- Billing (Customer, VAT, Subscription)
- Users, Invitations, Access
- CLI Usage
- Configuration
- Supported Entity Types
- Error Handling & Recovery
- State Management
- Rate Limiting
- Environment Variables
- API Reference (Configs)
- Examples
Installation
npm install @axeptio/provisioningQuick Start
import {
createClient,
createExecutor,
OrganizationProvisioner,
ProjectProvisioner,
CookieConfigurationProvisioner,
TermsConfigurationProvisioner,
ProvisioningCallbacks,
} from '@axeptio/provisioning';
const client = createClient({ apiKey: 'your-api-key', environment: 'staging' });
const executor = createExecutor(client, 'my-migration-2024');
const org = new OrganizationProvisioner('org', {
companyName: 'Example Corp',
email: '[email protected]',
country: 'FR', line1: '123 Rue de la Paix', city: 'Paris', postalCode: '75001',
isProfessional: 'YES',
});
const project = new ProjectProvisioner('project', {
name: 'Example Website', websiteURL: 'https://example.com', locales: ['en', 'fr'],
});
const cookies = new CookieConfigurationProvisioner('cookies', {
projectId: '', language: 'en', country: 'FR',
steps: [{ layout: 'welcome', title: 'We use cookies' }],
});
const terms = new TermsConfigurationProvisioner('terms', {
projectId: '',
config: { language: 'en', title: 'Terms of Service', name: 'tos', mandatory_download: false },
content: {
sections: [
{ uid: 'intro', name: 'introduction', title: 'Introduction', blocks: [
{ type: 'title', content: 'Introduction' },
{ type: 'richText', content: 'Welcome to our service.' },
] }]
},
});
project
.addConfiguration(cookies)
.addConfiguration(terms)
.onSuccess(ProvisioningCallbacks.publishProject(['cookies']))
.onSuccess(ProvisioningCallbacks.startScan({ maxPages: 10 }));
org.addProject(project);
executor.addOrganization(org);
await executor.execute({ mode: 'dryrun', organizationBatchSize: 1, projectBatchSize: 2, autoCheckpoint: true });Post-Provisioning Callbacks
Add callbacks to execute actions after successful or failed provisioning:
import { ProvisioningCallbacks } from '@axeptio/provisioning';
// Single callback
project.onSuccess(ProvisioningCallbacks.publishProject(['cookies', 'tcf']));
// Multiple callbacks
project
.onSuccess(ProvisioningCallbacks.publishProject())
.onSuccess(ProvisioningCallbacks.startScan({
maxTabs: 3,
maxPages: 10,
testCMP: true,
languages: ['en', 'fr']
}))
.onFailure(ProvisioningCallbacks.logFailure('Project creation failed'));
// Custom callbacks
project.onSuccess(async (result: Project, context) => {
console.log(`Project created: ${result.name} (${result._id})`);
await sendNotificationEmail(result.name);
await updateExternalSystem(result._id);
});
// Chain multiple callbacks
project.onSuccess(ProvisioningCallbacks.chain(
ProvisioningCallbacks.publishProject(['cookies']),
ProvisioningCallbacks.logSuccess('Project published'),
customNotificationCallback
));Built-in Callbacks
| Callback | Description | Parameters |
|----------|-------------|------------|
| publishProject(services?) | Publish project configurations | services: string[] - Default: ['cookies', 'tcf'] |
| startScan(config) | Launch automator scan job | maxTabs, maxPages, testCMP, languages |
| logSuccess(message?) | Log successful completion | message: string - Optional custom message |
| logFailure(message?) | Log failure details | message: string - Optional custom message |
| chain(...callbacks) | Execute multiple callbacks in sequence | callbacks: ProvisioningCallback[] |
Note: Callbacks are preserved during state recovery. When resuming from a saved state, callbacks will still execute for newly completed nodes, but not for previously completed ones.
Projects Groups
Projects groups are organizational folders used in the backoffice to organize projects. They execute after projects are created so their projectIds array can be populated.
// Create projects first
const project1 = new ProjectProvisioner('proj-1', projectData1);
const project2 = new ProjectProvisioner('proj-2', projectData2);
// Create a projects group and add projects to it
const projectsGroup = new ProjectsGroupProvisioner('group-1', {
name: 'Website Projects',
organizationId: 'org-123' // Optional - will be set from context
})
.addProject(project1) // Projects will be referenced by ID
.addProject(project2)
.onSuccess(ProvisioningCallbacks.logSuccess('Projects group created'));
// Add to executor
org.addProject(project1);
org.addProject(project2);
executor.addOrganization(org);
executor.addProjectsGroup(projectsGroup); // Executed after projectsExecution Order: Projects Groups are executed after Projects to ensure project IDs are available for the projectIds array.
Entity Recipes (copy-paste)
Small, focused snippets to reduce context load. Replace IDs/emails as needed.
Organizations & Projects
const org = new OrganizationProvisioner('org', { companyName: 'ACME', email: '[email protected]', country: 'FR', line1: '1 Rue', city: 'Paris', postalCode: '75001', isProfessional: 'YES' });
const project = new ProjectProvisioner('proj', { name: 'Website', websiteURL: 'https://acme.com' });
org.addProject(project);
executor.addOrganization(org);Projects Groups
const group = new ProjectsGroupProvisioner('group', { name: 'Web Properties' }).addProject(project);
executor.addProjectsGroup(group);Cookies Configuration
const cookies = new CookieConfigurationProvisioner('cookies', {
projectId: '', language: 'en', country: 'FR',
steps: [{ layout: 'welcome', title: 'We use cookies' }],
});
project.addConfiguration(cookies);Auto-categorization mode (bulk-friendly)
Optionally let the provisioner build steps from a list of vendor solution IDs. Vendors are assigned to their most frequent category, cookie-step templates are used to shape steps, and an optional ConsentWall can be added as a special step.
const autoCookies = new CookieConfigurationProvisioner('cookies-auto', {
projectId: '',
language: 'en',
autoCategorize: {
vendorIds: ['64a...','64b...'],
language: 'en',
withConsentWall: true,
},
});
project.addConfiguration(autoCookies);Notes:
- Reorders 'info' to index 1 when present, 'other' to last.
- Supports
specialStepsfor the ConsentWall. - Uses
/vendors/categories,/vendors/solutions/{id}/{language}, and/templates/cookie-stependpoints.
Project Design & Stylesheet
Provision project theming with a simple style guide. We expose types and a helper to mirror WidgetGenerator behavior without pulling its internals.
Types:
StyleGuideInput— { lightColor, darkColor, themeColor, isDarkMode?, isMonochrome?, font? } (hex colors without '#')ProjectStylesheet— shape compatible withProjectInput(colors,fonts,widgetStyle,overlayStyle,isCustomStyle)
Helper:
integrateStyleGuide(style: StyleGuideInput): ProjectStylesheet
Example:
import { ProjectProvisioner, integrateStyleGuide, type StyleGuideInput } from '@axeptio/provisioning';
const sg: StyleGuideInput = {
lightColor: 'F5BD55',
darkColor: '000000',
themeColor: 'f6c434',
isDarkMode: false,
isMonochrome: false,
font: 'Lato',
};
const stylesheet = integrateStyleGuide(sg);
const project = new ProjectProvisioner('project-1', {
name: 'Website',
websiteURL: 'https://example.com',
...stylesheet,
});Notes:
ProjectInput.colors,widgetStyle, andoverlayStylesupport extended fields (e.g.,toggle_on,consent_button_*,borderRadius,position.side).isCustomStyle: trueis set by the helper to indicate custom design.
Terms (ContractsV2) Configuration
const terms = new TermsConfigurationProvisioner('terms', {
projectId: '',
config: { language: 'en', title: 'Terms of Service', name: 'tos' },
content: { sections: [{ uid: 'intro', name: 'introduction', blocks: [ { type: 'title', content: 'Introduction' }, { type: 'richText', content: 'Welcome.' } ] }] }
});
project.addConfiguration(terms);Vendors (Company & Solution)
const company = new VendorCompanyProvisioner('vendor-co', { name: 'Acme Analytics', domain: 'acme-analytics.example' });
const solution = new VendorSolutionProvisioner('vendor-sol', {
name: 'acme-analytics',
title: { __lang: { en: 'Acme Analytics' } },
website: { __lang: { en: 'https://acme.example' } },
shortDescription: { __lang: { en: 'Analytics' } },
categoryIds: [],
} as any);
executor.addVendorCompany(company);
executor.addVendorSolution(solution);Billing (Customer, VAT, Subscription)
// 1) Customer
const customer = await client.createCustomer({
email: '[email protected]', name: 'Example Corp',
tax_exempt: 'none', preferred_locales: ['fr-FR','en-US'],
address: { line1: '123 Rue', city: 'Paris', country: 'FR', postal_code: '75001' },
metadata: { isProfessional: 'YES', vatNumber: 'FR123...', contactName: 'Jane' },
expand: ['tax_ids','invoice_settings.default_payment_method','sources'],
});
// 2) VAT
await client.createCustomerTaxId(customer.id, { type: 'eu_vat', value: 'FR123...' });
// 3) Subscription
project.setSubscription(new SubscriptionProvisioner('sub', {
customer: customer.id,
items: [{ price: 'price_agency_monthly', quantity: 1 }],
payment_behavior: 'default_incomplete', currency: 'eur',
expand: ['latest_invoice','discounts','items.price'],
metadata: { organizationId: '...', userId: '...' },
}));Users, Invitations, Access
const user = new UserProvisioner('user', { email: '[email protected]', password: 'Secret123!', displayName: 'New User', data: { preferredLanguage: 'en', acceptTerms: true }});
user.addInvitation(new InvitationProvisioner('inv', { email: '[email protected]', data: { collection: 'organizations', id: 'orgId' }}));
executor.addUser(user);
executor.addGroupAssignment(new GroupManagerProvisioner('assign', { userId: '', projectId: 'projectId', action: 'add' }));User Management & Access Control
Provision users and manage their access to organizations and projects:
import {
UserProvisioner,
InvitationProvisioner,
GroupManagerProvisioner
} from '@axeptio/provisioning';
// Create user with invitations
const user = new UserProvisioner('user-1', {
email: '[email protected]',
password: 'SecurePassword123',
displayName: 'New User',
data: {
preferredLanguage: 'en',
acceptTerms: true
}
})
.onSuccess(ProvisioningCallbacks.logSuccess('User created successfully'))
.onSuccess(ProvisioningCallbacks.addUserToOrganization('org-id'));
// Add invitation to organization
const invitation = new InvitationProvisioner('invite-1', {
email: '[email protected]',
data: {
collection: 'organizations',
id: 'org-id-123',
templateVars: {
organization: { companyName: 'Example Corp' }
}
}
});
user.addInvitation(invitation);
// Manage group assignments
const groupAssignment = new GroupManagerProvisioner('group-1', {
userId: 'user-id-from-context',
projectId: 'project-id-123',
action: 'add'
});
executor.addUser(user);
executor.addGroupAssignment(groupAssignment);User Management Callbacks
| Callback | Description | Usage |
|----------|-------------|-------|
| addUserToOrganization(orgId) | Add user to organization | After user creation |
| addUserToProject(projectId) | Add user to project | After user creation |
| logSuccess(message?) | Log successful completion | After successful user creation |
CLI Usage
# Set admin credentials
export AXEPTIO_ADMIN_USERNAME="[email protected]"
export AXEPTIO_ADMIN_PASSWORD="your-admin-password"
# Run provisioning
axeptio-provision run my-migration config.json --admin-username $AXEPTIO_ADMIN_USERNAME --admin-password $AXEPTIO_ADMIN_PASSWORD
# Check status
axeptio-provision status --admin-username $AXEPTIO_ADMIN_USERNAME --admin-password $AXEPTIO_ADMIN_PASSWORD
# Resume after interruption
axeptio-provision resume my-migration --admin-username $AXEPTIO_ADMIN_USERNAME --admin-password $AXEPTIO_ADMIN_PASSWORD
# View checkpoints
axeptio-provision checkpoints my-migration --admin-username $AXEPTIO_ADMIN_USERNAME --admin-password $AXEPTIO_ADMIN_PASSWORD
# Rollback created entities
axeptio-provision rollback my-migration --admin-username $AXEPTIO_ADMIN_USERNAME --admin-password $AXEPTIO_ADMIN_PASSWORD
# Clean up state
axeptio-provision clean my-migration --admin-username $AXEPTIO_ADMIN_USERNAME --admin-password $AXEPTIO_ADMIN_PASSWORDConfiguration
Create a config.json file for execution settings:
{
"mode": "dryrun",
"organizationBatchSize": 3,
"projectBatchSize": 5,
"configurationBatchSize": 10,
"autoCheckpoint": true,
"checkpointInterval": 300,
"continueOnError": false,
"maxRetries": 3,
"retryDelay": 1000
}Supported Entity Types
- Organizations - Company entities that own projects
- Projects - Individual compliance projects
- Projects Groups - Organizational folders for projects (backoffice convenience)
- Users - User accounts with authentication and access control
- Invitations - User invitations to organizations/projects
- Group Assignments - User access management for organizations/projects
- Cookie Configurations - Cookie consent widgets
- TCF Configurations - IAB TCF compliance setups
- DPO Configurations - Data Protection Officer contacts
- Terms Configurations - Legal terms and conditions (ContractsV2)
- Subs Configurations - Data processing subscriptions (formerly Processing)
- Subscriptions - Billing subscriptions (Stripe)
Error Handling & Recovery
The package automatically handles:
- Network failures with exponential backoff
- Rate limiting with intelligent queuing
- Partial failures with detailed error reporting
- State corruption with checkpoint recovery
Resuming After Interruption
// Resume from last saved state
const executor = await ResumableProvisioningExecutor.fromState(
'my-migration-2024',
'./provisioning-state',
client
);
await executor.execute(config);Rollback Created Entities
// Rollback all created entities in reverse order
await executor.rollback();State Management
State is automatically persisted to disk:
./provisioning-state/
├── my-migration-2024.json # Main state file
└── checkpoints/
└── my-migration-2024/
├── 2024-01-15T10-30-00-execution-start.json
└── 2024-01-15T10-45-00-organizations-completed.jsonRate Limiting
The client automatically handles Axeptio's rate limits:
- Authentication: 60 requests per 5 minutes
- Scan endpoints: 15 requests per minute
- General API: 50 requests per minute (configurable)
Environment Variables
[email protected]
AXEPTIO_ADMIN_PASSWORD=your-admin-password
AXEPTIO_ENVIRONMENT=staging # or productionCLI Commands
| Command | Description |
|---------|-------------|
| run <state-id> <config-file> | Start new provisioning |
| resume <state-id> | Resume interrupted provisioning |
| status | Show all provisioning states |
| checkpoints <state-id> | List available checkpoints |
| rollback <state-id> | Delete all created entities |
| clean <state-id> | Remove state files |
API Reference
Client Configuration
interface ClientConfig {
apiKey: string;
baseURL?: string;
environment?: 'staging' | 'production';
maxRetries?: number;
retryDelay?: number;
rateLimitRpm?: number;
}Extended Client Methods
New helper endpoints exposed by the client for bulk cookie configuration generation:
Templates & Steps
getCookieStepTemplates()— list available cookie-step templatesgetCookieStepTemplateByName(name)— fetch a specific cookie-step templategetCustomCookieTemplate({ language, country?, subdivision?, steps })— generate a cookie template from step names
Vendors & Categories
getVendorCategories(params?)getVendorSolutionLocalized(id, language)
Project Admin Actions
lockProject(projectId)/unlockProject(projectId)unpublishProject(projectId)duplicateProject(projectId, { name?, websiteURL? })
Style and Template Helpers
Cookies
buildCookieConfiguration(client, { projectId, language, stepNames?, stepsOverride?, published?, googleConsentMode? })positionStepByNameAndIndex(steps, name, index)/concatenateOtherSteps(steps)
Design
integrateStyleGuide(style: StyleGuideInput): ProjectStylesheet
Execution Configuration
interface ExecutionConfig {
mode: 'dryrun' | 'staging' | 'production';
organizationBatchSize?: number;
projectBatchSize?: number;
configurationBatchSize?: number;
autoCheckpoint?: boolean;
checkpointInterval?: number;
continueOnError?: boolean;
maxRetries?: number;
retryDelay?: number;
}Examples
See the examples/ directory for complete usage:
basic-usage.ts— Org, Project, Cookies, Terms, optional Subscriptionorganizations-and-projects.ts— Multiple projects + projects groupcookies-config.ts— Cookie configuration with steps/vendorsterms-config.ts— ContractsV2 Terms with config/content modelvendors.ts— Vendor company and solution creationbilling.ts— Stripe customer + VAT + subscriptionusers-and-access.ts— Users, invitations, and project accessconfig.json— Execution configuration
License
© Axeptio 2025 - Proprietary
