This skill should be used when the user asks to "integrate web api", "add web api", "connect to dataverse", "add api integration", "set up web api calls", "integrate api for my tables", "add crud operations", "hook up web api", "add data fetching", "connect frontend to dataverse", or wants to integrate Power Pages Web API into their site's frontend code with proper permissions and deployment. This skill orchestrates the full integration lifecycle: code integration, permissions setup, and deployment.
78
76%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Passed
No known issues
Optimize this skill with Tessl
npx tessl skill review --optimize ./plugins/power-pages/skills/integrate-webapi/SKILL.mdIntegrate Power Pages Web API into a code site's frontend. This skill orchestrates the full lifecycle: analyzing where integrations are needed, implementing API client code for each table, configuring permissions and site settings, and deploying the site.
powerPagesApi.ts client. Once that exists, remaining tables can be processed in parallel since each creates independent files (types, service, hooks).table-permissions-architect and webapi-settings-architect agents are independent — invoke them in parallel rather than sequentially..powerpages-site folder must exist before table permissions and site settings can be configured. Integration code can be written without it, but permissions cannot.Prerequisites:
- An existing Power Pages code site created via
/create-site- A Dataverse data model (tables/columns) already set up via
/setup-datamodelor created manually- The site must be deployed at least once (
.powerpages-sitefolder must exist) for permissions setup
Initial request: $ARGUMENTS
webapi-integration agent for each table/deploy-site if confirmedGoal: Locate the Power Pages project root and confirm that prerequisites are met
Actions:
Look for powerpages.config.json in the current directory or immediate subdirectories to find the project root.
Get-ChildItem -Path . -Filter "powerpages.config.json" -Recurse -Depth 1If not found: Tell the user to create a site first with /create-site.
Read powerpages.config.json to get the site name:
Get-Content "<PROJECT_ROOT>/powerpages.config.json" | ConvertFrom-JsonRead package.json to determine the framework (React, Vue, Angular, or Astro). See ${CLAUDE_PLUGIN_ROOT}/references/framework-conventions.md for the full framework detection mapping.
Look for .datamodel-manifest.json to discover available tables:
**/.datamodel-manifest.jsonIf found, read it — this is the primary source for table discovery.
Look for the .powerpages-site folder:
**/.powerpages-siteIf not found: Warn the user that the permissions phase (Phase 5) will require deployment first. The integration code (Phases 2–4) can still proceed.
Output: Confirmed project root, framework, data model availability, and deployment status
Goal: Analyze the site code and data model to identify all tables needing Web API integration
Actions:
Use the Explore agent (via Task tool with agent_type: "explore") to analyze the site code and data model. The Explore agent should answer these questions:
Ask the Explore agent to identify all Dataverse tables that need Web API integration by examining:
.datamodel-manifest.json — List of tables and their columnssrc/**/*.{ts,tsx,js,jsx,vue,astro} — Source code files that reference table data, mock data, or placeholder API calls/_api/ fetch patterns in the codeTODO or FIXME comments mentioning API integrationPrompt for the Explore agent:
"Analyze this Power Pages code site and identify all Dataverse tables that need Web API integration. Check
.datamodel-manifest.jsonfor the data model, then search the source code for: mock data arrays, hardcoded data, placeholder fetch calls to/_api/, TypeScript interfaces matching Dataverse column patterns (publisher prefix likecr*_), TODO/FIXME comments about API integration, and components that display table data. For each table found, report: the table logical name, the entity set name (plural), which source files reference it, what operations are needed (read/create/update/delete), and whether an existing API client or service already exists insrc/shared/orsrc/services/. Also check ifsrc/shared/powerPagesApi.tsalready exists."
The Explore agent should also report:
src/shared/powerPagesApi.ts (or equivalent API client) already existssrc/shared/services/ or src/services/src/types/This avoids duplicating work that was already done.
From the Explore agent's findings, compile a list of tables needing integration:
| Table | Logical Name | Entity Set | Operations | Files Referencing | Existing Service |
|---|---|---|---|---|---|
| Products | cr4fc_product | cr4fc_products | CRUD | ProductList.tsx, ProductCard.tsx | None |
| Categories | cr4fc_category | cr4fc_categories | Read | CategoryFilter.tsx | None |
Output: Complete integration manifest listing all tables, their operations, referencing files, and existing service status
Goal: Present the integration manifest to the user and confirm which tables to integrate
Actions:
Show the user:
Use AskUserQuestion to confirm:
| Question | Options |
|---|---|
| I found the following tables that need Web API integration: [list tables]. Which tables should I integrate? | All of them (Recommended), Let me select specific tables, I need to add more tables |
If the user selects specific tables or adds more, update the integration manifest accordingly.
Output: User-confirmed list of tables to integrate
Goal: Create Web API integration code for each confirmed table using the webapi-integration agent
Actions:
For each table, use the Task tool to invoke the webapi-integration agent at ${CLAUDE_PLUGIN_ROOT}/agents/webapi-integration.md:
Prompt template for the agent:
"Integrate Power Pages Web API for the [Table Display Name] table.
- Table logical name:
[logical_name]- Entity set name:
[entity_set_name]- Operations needed: [read/create/update/delete]
- Framework: [React/Vue/Angular/Astro]
- Project root: [path]
- Source files referencing this table: [list of files]
- Data model manifest path: [path to .datamodel-manifest.json if available]
Create the TypeScript types, CRUD service layer, and framework-specific hooks/composables. Replace any mock data or placeholder API calls in the referencing source files with the new service."
The first table must be processed alone — it creates the shared powerPagesApi.ts client that all other tables depend on. After the first table completes and the shared client exists:
src/shared/powerPagesApi.tsTask calls — each table creates independent files (its own types in src/types/, service in src/shared/services/, and hook/composable), so there are no conflictsIf there is only one table, this step is simply sequential.
After each agent completes (or after all parallel agents complete), verify the output:
After all integrations are complete, stage and commit:
git add -A
git commit -m "Add Web API integration for [table names]"Output: Integration code created for all confirmed tables, verified and committed
Goal: Validate that all expected integration files exist, imports are correct, and the project builds successfully
Actions:
For each integrated table, confirm the following files exist:
src/types/ (e.g., src/types/product.ts)src/shared/services/ or src/services/ (e.g., productService.ts)src/shared/hooks/useProducts.ts for React, src/composables/useProducts.ts for Vue)Also verify:
src/shared/powerPagesApi.ts exists/_api/ endpointsRun the project build to catch any import errors, type errors, or missing dependencies:
npm run buildIf the build fails, fix the issues before proceeding. Common issues:
Present a table summarizing the verification:
| Table | Types | Service | Hook/Composable | API References |
|---|---|---|---|---|
| Products | src/types/product.ts | src/shared/services/productService.ts | src/shared/hooks/useProducts.ts | /_api/cr4fc_products |
| ... | ... | ... | ... | ... |
Build status: Pass / Fail (with details)
Output: All integration files verified, project builds successfully
Goal: Configure table permissions and Web API site settings for all integrated tables using the table-permissions-architect and webapi-settings-architect agents
Actions:
Both agents require the .powerpages-site folder. If it doesn't exist:
Use AskUserQuestion:
| Question | Options |
|---|---|
The .powerpages-site folder was not found. The site needs to be deployed once before permissions and site settings can be configured. Would you like to deploy now? | Yes, deploy now (Recommended), Skip permissions for now — I'll set them up later |
If "Yes, deploy now": Invoke /deploy-site first, then resume this phase.
If "Skip": Skip to Phase 7 with a note that permissions and site settings still need to be configured.
Ask the user how they want to define the permissions using the AskUserQuestion tool:
Question: "How would you like to define the Web API permissions and settings for your site?"
| Option | Description |
|---|---|
| Upload an existing permissions diagram | Provide an image (PNG/JPG) or Mermaid diagram of your existing permissions structure |
| Let the architects figure it out | The Table Permissions Architect and Web API Settings Architect will analyze your site's code, data model, and Dataverse environment, then propose permissions and settings automatically |
Route to the appropriate path:
If the user chooses to upload an existing diagram:
Ask the user to provide their permissions diagram. Supported formats:
Read tool to view the image and extract web roles, table permissions, CRUD flags, scopes, and site settings from itParse the diagram into structured format:
.powerpages-site/web-roles/ by name to get their UUIDsWebapi/<table>/enabled and Webapi/<table>/fields — CRITICAL: fields normally list specific column logical names; only use * when the site relies on aggregate OData queries ($apply/aggregate) that otherwise fail with 403Validate column names against Dataverse — Even when using a user-provided diagram, query Dataverse for each table's column LogicalNames and verify that every column in the Webapi/<table>/fields values uses the exact Dataverse LogicalName (case-sensitive). Correct any mismatches before creating files.
Cross-check with existing configuration in .powerpages-site/ to identify which permissions and site settings are new vs. already exist.
Generate a Mermaid flowchart from the parsed data (if the user provided an image or text) for visual confirmation.
Present the parsed permissions plan to the user for approval using AskUserQuestion:
| Question | Options |
|---|---|
| Does this permissions plan look correct? | Approve and create files (Recommended), Request changes, Cancel |
Proceed directly to section 6.4: Create Permission & Settings Files with the parsed data.
If the user chooses to let the architects figure it out, proceed to section 6.3: Invoke Table Permissions Agent.
These two agents are independent — invoke them in parallel using two Task calls simultaneously:
Use the Task tool to invoke the table-permissions-architect agent at ${CLAUDE_PLUGIN_ROOT}/agents/table-permissions-architect.md:
Prompt:
"Analyze this Power Pages code site and propose table permissions. The following tables have been integrated with Web API: [list of tables integrated in Phase 4]. Check for existing web roles and table permissions. Propose a complete table permissions plan covering all integrated tables. After I approve the plan, create the web role and table permission YAML files using the deterministic scripts."
The agent will:
create-web-role.jscreate-table-permission.jsUse the Task tool to invoke the webapi-settings-architect agent at ${CLAUDE_PLUGIN_ROOT}/agents/webapi-settings-architect.md:
Prompt:
"Analyze this Power Pages code site and propose Web API site settings. The following tables have been integrated with Web API: [list of tables integrated in Phase 4]. Check for existing site settings and query Dataverse for exact column LogicalNames. Propose site settings with case-sensitive validated column names. After I approve the plan, create the site setting YAML files using the deterministic scripts."
The agent will:
create-site-setting.jsWait for both agents to complete before proceeding to 6.4.
This section applies only to Path A (user-provided permissions diagram). For Path B, the architect agents create the files directly in section 6.3.
After parsing the user's diagram, create the YAML files using the deterministic scripts below. Do NOT write YAML files manually — always use these scripts which handle UUID generation, field ordering, formatting, and file naming automatically.
If the plan requires new web roles that don't already exist, create them first (their UUIDs are needed for table permissions):
node "${CLAUDE_PLUGIN_ROOT}/skills/create-webroles/scripts/create-web-role.js" --projectRoot "<PROJECT_ROOT>" --name "<Role Name>" [--anonymous] [--authenticated]Capture the JSON output ({ "id": "<uuid>", "filePath": "<path>" }) — use the id as the --webRoleIds value when creating table permissions.
For each table permission in the plan. Process parent permissions before child permissions — children need the parent's UUID from the JSON output.
For Global/Contact/Account/Self scope:
node "${CLAUDE_PLUGIN_ROOT}/scripts/create-table-permission.js" --projectRoot "<PROJECT_ROOT>" --permissionName "<Permission Name>" --tableName "<table_logical_name>" --webRoleIds "<uuid1,uuid2>" --scope "Global" [--read] [--create] [--write] [--delete] [--append] [--appendto]
node "${CLAUDE_PLUGIN_ROOT}/scripts/create-table-permission.js" --projectRoot "<PROJECT_ROOT>" --permissionName "<Permission Name>" --tableName "<table_logical_name>" --webRoleIds "<uuid1,uuid2>" --scope "Contact" --contactRelationshipName "<lookup_to_contact>" [--read] [--create] [--write] [--delete] [--append] [--appendto]
node "${CLAUDE_PLUGIN_ROOT}/scripts/create-table-permission.js" --projectRoot "<PROJECT_ROOT>" --permissionName "<Permission Name>" --tableName "<table_logical_name>" --webRoleIds "<uuid1,uuid2>" --scope "Account" --accountRelationshipName "<lookup_to_account>" [--read] [--create] [--write] [--delete] [--append] [--appendto]
node "${CLAUDE_PLUGIN_ROOT}/scripts/create-table-permission.js" --projectRoot "<PROJECT_ROOT>" --permissionName "<Permission Name>" --tableName "<table_logical_name>" --webRoleIds "<uuid1,uuid2>" --scope "Self" [--read] [--create] [--write] [--delete] [--append] [--appendto]For Parent scope (requires parent permission UUID and relationship name):
node "${CLAUDE_PLUGIN_ROOT}/scripts/create-table-permission.js" --projectRoot "<PROJECT_ROOT>" --permissionName "<Permission Name>" --tableName "<table_logical_name>" --webRoleIds "<uuid1>" --scope "Parent" --parentPermissionId "<parent-uuid>" --parentRelationshipName "<relationship_name>" [--read] [--create] [--write] [--delete] [--append] [--appendto]Each invocation outputs { "id": "<uuid>", "filePath": "<path>" }. Use the id as --parentPermissionId for child permissions.
For each site setting in the plan:
Enabled setting (boolean):
node "${CLAUDE_PLUGIN_ROOT}/scripts/create-site-setting.js" --projectRoot "<PROJECT_ROOT>" --name "Webapi/<table>/enabled" --value "true" --description "Enable Web API access for <table> table" --type "boolean"Fields setting (string — use the validated column names from the diagram):
node "${CLAUDE_PLUGIN_ROOT}/scripts/create-site-setting.js" --projectRoot "<PROJECT_ROOT>" --name "Webapi/<table>/fields" --value "<comma-separated-validated-columns>" --description "Allowed fields for <table> Web API access"Inner error setting (boolean, optional for debugging):
node "${CLAUDE_PLUGIN_ROOT}/scripts/create-site-setting.js" --projectRoot "<PROJECT_ROOT>" --name "Webapi/error/innererror" --value "true" --description "Enable detailed error messages for debugging" --type "boolean"Important: The --value for fields settings MUST use exact Dataverse LogicalNames (case-sensitive, all lowercase) for normal CRUD/read scenarios. Using incorrect casing causes 403 Forbidden errors.
Aggregate exception: If the site uses aggregate OData queries ($apply, aggregate, grouped totals, etc.), set Webapi/<table>/fields to *. Power Pages rejects some aggregate queries with 403 unless wildcard field access is enabled.
Lookup columns: For every lookup column, include both the LogicalName (cr87b_categoryid) AND the OData computed attribute (_cr87b_categoryid_value) in the fields value. The Power Pages Web API does a literal match — the LogicalName is needed for write operations, the _..._value form is needed for read operations ($select, $filter). Missing either form causes 403 errors.
Stage and commit the permission and settings files:
git add -A
git commit -m "Add table permissions and Web API site settings for [table names]"Output: Table permissions and site settings created, verified, and committed
Goal: Present a summary of all work performed and offer deployment
Actions:
Reference:
${CLAUDE_PLUGIN_ROOT}/references/skill-tracking-reference.md
Follow the skill tracking instructions in the reference to record this skill's usage. Use --skillName "IntegrateWebApi".
Present a summary of everything that was done:
| Step | Status | Details |
|---|---|---|
| API Client | Created/Existed | src/shared/powerPagesApi.ts |
| Types | Created | src/types/product.ts, src/types/category.ts |
| Services | Created | src/shared/services/productService.ts, etc. |
| Hooks | Created | src/shared/hooks/useProducts.ts, etc. |
| Components Updated | X files | Mock data replaced with API calls |
| Table Permissions | Created | X permission files |
| Site Settings | Created | X setting files |
Use AskUserQuestion:
| Question | Options |
|---|---|
| The Web API integration and permissions are ready. To make everything live, the site needs to be deployed. Would you like to deploy now? | Yes, deploy now (Recommended), No, I'll deploy later |
If "Yes, deploy now": Invoke the /deploy-site skill to deploy the site.
If "No, I'll deploy later": Acknowledge and remind:
"No problem! Remember to deploy your site using
/deploy-sitewhen you're ready. The Web API calls will not work until the site is deployed with the new permissions."
After deployment (or if skipped), remind the user:
Webapi/<table>/fields not matching the exact Dataverse LogicalName (case-sensitive — must be all lowercase). If the failing request uses aggregate OData ($apply, aggregate, grouped totals), also verify Webapi/<table>/fields is set to *.Webapi/error/innererror was enabled for debugging, disable it before going liveOutput: Summary presented, deployment completed or deferred, post-deploy guidance provided
.powerpages-site missing)Before starting Phase 1, create a task list with all phases using TaskCreate:
| Task subject | activeForm | Description |
|---|---|---|
| Verify site exists | Verifying site prerequisites | Locate project root, detect framework, check data model and deployment status |
| Explore integration points | Analyzing code for integration points | Use Explore agent to discover tables, existing services, and compile integration manifest |
| Review integration plan | Reviewing integration plan with user | Present findings and confirm which tables to integrate |
| Implement integrations | Implementing Web API integrations | Invoke webapi-integration agent for first table (creates shared client), then remaining tables in parallel, verify output, git commit |
| Verify integrations | Verifying integrations | Validate all expected files exist, check imports and API references, run project build |
| Setup permissions and settings | Configuring permissions and site settings | Choose permissions source (upload diagram or architects), invoke table-permissions-architect and webapi-settings-architect agents in parallel, create YAML files with case-sensitive validated column names, git commit |
| Review and deploy | Reviewing summary and deploying | Present summary, ask about deployment, provide post-deploy guidance |
Mark each task in_progress when starting it and completed when done via TaskUpdate. This gives the user visibility into progress and keeps the workflow deterministic.
Begin with Phase 1: Verify Site Exists
66a61c6
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.